En este momento estás viendo Cómo cerrar Unity sin cerrar toda la aplicación al cambiar fragmentos en Android ¿Estudio?

 – Unity

Cómo cerrar Unity sin cerrar toda la aplicación al cambiar fragmentos en Android ¿Estudio? – Unity

Cómo cerrar Unity sin cerrar toda la aplicación al cambiar fragmentos en Android ¿Estudio?

– UnityAssets3Free

bienvenido , me llamo jorge y esta vez os traigo
nueva pregunta curiosa

Tengo una aplicación en la que el usuario puede recorrer diferentes fragmentos usando BottomNavigationView y uno de esos fragmentos es una aplicación Unity3D. Entonces, cuando abro el fragmento de Unity, funciona, pero cuando abro otro fragmento y vuelvo a abrir el fragmento de Unity, se bloquea. ¿Cómo soluciono esto? Aquí está mi código.

MainActivity.java

public class MainActivity extends AppCompatActivity {

BottomNavigationView mBottomNavigationView;
NavController mNavController;
NavDestination mDestination;
AppBarConfiguration appBarConfiguration;
String tab;
private boolean doubleBackToExitPressedOnce ;

@Override
protected void onCreate(Bundle savedInstanceState) 

    super.onCreate(savedInstanceState);
    boolean b = this.requestWindowFeature(Window.FEATURE_NO_TITLE);
    this.setContentView(R.layout.activity_main);

    ActionBar mActionBar = getSupportActionBar();
    mActionBar.setDisplayShowHomeEnabled(false);
    mActionBar.setDisplayShowTitleEnabled(false);
    LayoutInflater li = LayoutInflater.from(this);
    View customView = li.inflate(R.layout.top_menu_custom, null);
    mActionBar.setCustomView(customView);
    mActionBar.setDisplayShowCustomEnabled(true);


    mBottomNavigationView = (BottomNavigationView) findViewById(R.id.nav_view);

    ImageButton profileButton = (ImageButton) customView.findViewById(R.id.profile_button);
    ImageButton notificationButton = (ImageButton) customView.findViewById(R.id.noti_button);

    profileButton.setOnClickListener(new View.OnClickListener() 
        @Override
        public void onClick(View view) 

            ProfileFragment profileFragment = new ProfileFragment();
            getSupportFragmentManager().beginTransaction()
                    .replace(R.id.nav_host_fragment,profileFragment)
                    .addToBackStack(tab)
                    .setReorderingAllowed(true)
                    .commit();
            mBottomNavigationView.setVisibility(View.GONE);
        
    );

    notificationButton.setOnClickListener(new View.OnClickListener() 
        @Override
        public void onClick(View view) 

            NotificationFragment notificationFragment = new NotificationFragment();
            getSupportFragmentManager().beginTransaction()
                    .replace(R.id.nav_host_fragment,notificationFragment)
                    .addToBackStack(tab)
                    .setReorderingAllowed(true)
                    .commit();
            mBottomNavigationView.setVisibility(View.GONE);
        
    );

    mBottomNavigationView.setItemIconTintList(null);
    mBottomNavigationView.setItemTextColor(ColorStateList.valueOf(getColor(R.color.black)));

    mNavController = Navigation.findNavController(this, R.id.nav_host_fragment);

    // Passing each menu ID as a set of Ids because each
    // menu should be considered as top level destinations.
    appBarConfiguration = new AppBarConfiguration.Builder(
            R.id.navigation_home, R.id.navigation_dashboard,R.id.navigation_map, R.id.navigation_card,R.id.navigation_deals)
            .build();

    NavigationUI.setupActionBarWithNavController(this, mNavController, appBarConfiguration);
    NavigationUI.setupWithNavController(mBottomNavigationView, mNavController);
    mNavController.addOnDestinationChangedListener(new NavController.OnDestinationChangedListener() 

        @Override
        public void onDestinationChanged(@NonNull NavController controller, @NonNull NavDestination destination, @Nullable Bundle arguments) 
            Toast.makeText(getApplicationContext(),"hi",Toast.LENGTH_SHORT).show();
            mDestination = mNavController.getCurrentDestination();
            tab = mDestination.toString();
        
    );




@Override
public void onBackPressed() 
    //Toast.makeText(getApplicationContext(), mDestination.toString(),Toast.LENGTH_SHORT).show();


    if (doubleBackToExitPressedOnce) 
        getSupportFragmentManager().popBackStackImmediate();
        mNavController.navigate(mDestination.getId());
        mBottomNavigationView.setVisibility(View.VISIBLE);
        super.onBackPressed();
        return;
    

    this.doubleBackToExitPressedOnce = true;
    Toast.makeText(this, "Please click BACK again to exit", Toast.LENGTH_SHORT).show();

    new Handler().postDelayed(new Runnable() 

        @Override
        public void run() 
            doubleBackToExitPressedOnce=false;
        
    , 2000);

UnityMapFragment

public class MapFragment extends Fragment{

protected UnityPlayer mUnityPlayer;
FrameLayout frameLayoutForUnity;

public MapFragment() 


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) 

    mUnityPlayer = new UnityPlayer(getActivity());
    View view = inflater.inflate(R.layout.fragment_map, container, false);
    this.frameLayoutForUnity = (FrameLayout) view.findViewById(R.id.frameLayoutForUnity);
    this.frameLayoutForUnity.addView(mUnityPlayer.getView(),
            FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);

    mUnityPlayer.requestFocus();
    mUnityPlayer.windowFocusChanged(true);
    return view;


@Override
public void onPause() 
    super.onPause();
    mUnityPlayer.pause();


@Override
public void onResume() 
    super.onResume();
    mUnityPlayer.resume();


// Quit Unity
@Override
public void onDestroy ()

    mUnityPlayer.quit();
    super.onDestroy();

2 respuestas 2

Así que logré darle una solución a este problema. No sé si es bueno hacerlo de esta manera o no, pero lo que hice fue instanciar el UnityPlayer en mi MainActivity y en mi fragmento llamo al UnityPlayer que se instancia en mi Main. Actividad.

MainActivity.java

public class MainActivity extends AppCompatActivity 

public BottomNavigationView mBottomNavigationView;
public NavController mNavController;
public NavDestination mDestination;
AppBarConfiguration appBarConfiguration;
String tab;
int onBackTimes = 0;

public UnityPlayer mUnityPlayer; <----Call unity player

@Override
protected void onCreate(Bundle savedInstanceState) 

    super.onCreate(savedInstanceState);

    mUnityPlayer = new UnityPlayer(this); <----UNITY PLAYER HERE

    boolean b = this.requestWindowFeature(Window.FEATURE_NO_TITLE);

    this.setContentView(R.layout.activity_main);

    ActionBar mActionBar = getSupportActionBar();
    mActionBar.setDisplayShowHomeEnabled(false);
    mActionBar.setDisplayShowTitleEnabled(false);
    LayoutInflater li = LayoutInflater.from(this);
    View customView = li.inflate(R.layout.top_menu_custom, null);
    mActionBar.setCustomView(customView);
    mActionBar.setDisplayShowCustomEnabled(true);


    mBottomNavigationView = (BottomNavigationView) findViewById(R.id.nav_view);

    ImageButton profileButton = (ImageButton) customView.findViewById(R.id.profile_button);
    ImageButton notificationButton = (ImageButton) customView.findViewById(R.id.noti_button);

    profileButton.setOnClickListener(new View.OnClickListener() 
        @Override
        public void onClick(View view) 

            ProfileFragment profileFragment = new ProfileFragment();
            getSupportFragmentManager().beginTransaction()
                    .replace(R.id.nav_host_fragment,profileFragment)
                    .addToBackStack(tab)
                    .setReorderingAllowed(true)
                    .commit();
            mBottomNavigationView.setVisibility(View.GONE);
        
    );

    notificationButton.setOnClickListener(new View.OnClickListener() 
        @Override
        public void onClick(View view) 

            NotificationFragment notificationFragment = new NotificationFragment();
            getSupportFragmentManager().beginTransaction()
                    .replace(R.id.nav_host_fragment,notificationFragment)
                    .addToBackStack(tab)
                    .setReorderingAllowed(true)
                    .commit();
            mBottomNavigationView.setVisibility(View.GONE);
        
    );

    mBottomNavigationView.setItemIconTintList(null);
    mBottomNavigationView.setItemTextColor(ColorStateList.valueOf(getColor(R.color.black)));

    mNavController = Navigation.findNavController(this, R.id.nav_host_fragment);

    // Passing each menu ID as a set of Ids because each
    // menu should be considered as top level destinations.
    appBarConfiguration = new AppBarConfiguration.Builder(
            R.id.navigation_home, R.id.navigation_dashboard,R.id.navigation_map, R.id.navigation_card,R.id.navigation_deals)
            .build();

    NavigationUI.setupActionBarWithNavController(this, mNavController, appBarConfiguration);
    NavigationUI.setupWithNavController(mBottomNavigationView, mNavController);
    mNavController.addOnDestinationChangedListener(new NavController.OnDestinationChangedListener() 

        @Override
        public void onDestinationChanged(@NonNull NavController controller, @NonNull NavDestination destination, @Nullable Bundle arguments) 
            mDestination = mNavController.getCurrentDestination();
            tab = mDestination.toString();
        
    );




@Override
public void onBackPressed() 

    Toast.makeText(this, "Please click BACK again to exit", Toast.LENGTH_SHORT).show();

    onBackTimes +=1;

    if(onBackTimes>1)
        LoginActivity.close.finish();
        finish();

    
    else
        getSupportFragmentManager().popBackStackImmediate();
        mBottomNavigationView.setVisibility(View.VISIBLE);
        super.onBackPressed();
        mNavController.navigate(mDestination.getId());
    

    new Handler().postDelayed(new Runnable() 

        @Override
        public void run() 
            onBackTimes=0;
        
    , 2000);



@Override
protected void onStop() 
    super.onStop();



//UNITY STUFF OVER HERE

@Override
protected void onPause() 
    super.onPause();
    mUnityPlayer.pause();


@Override protected void onResume()

    super.onResume();
    mUnityPlayer.resume();


@Override
protected void onDestroy()
    super.onDestroy();



UnityMapFragment

public class MapFragment extends Fragment{

private MainActivity mUnityMainActivity;
private UnityPlayer mUnityPlayer;

public MapFragment() 


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) 

    //this code calls the UNITYPLAYER from MainActivity and return it here
    mUnityMainActivity = (MainActivity) getActivity();
    View unityPlayViewer = mUnityMainActivity.mUnityPlayer.getView();
    mUnityMainActivity.mUnityPlayer.requestFocus();
    mUnityMainActivity.mUnityPlayer.windowFocusChanged(true);

    return unityPlayViewer;


/** FOR UNITY **/
@Override
public void onPause() 
    super.onPause();
    mUnityMainActivity.mUnityPlayer.pause();


// Resume Unity
@Override public void onResume()

    super.onResume();
    mUnityMainActivity.mUnityPlayer.resume();

No sé por qué tengo que incluir OnPause, OnResume, etc. en ambos archivos, pero si uno de ellos no lo tiene, falla.

El problema es que se crea un nuevo UnityPlayer cada vez que cambiamos a unity fragment y esto bloquea la aplicación. Entonces necesitamos crear UnityPlayer solo por primera vez o solo cuando el reproductor se detiene. Esto funciona de mi lado.

En la clase UnityFragment, mis variables globales:

protected UnityPlayer mUnityPlayer;
private View view;
private FrameLayout frameLayoutForUnity;

En el interior onCreate se crea un nuevo UnityPlayer, al que se llama solo por primera vez:

@Override
public void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    mUnityPlayer = new UnityPlayer(getActivity()); // create Unity Player

En el interior onCreateView actualizamos la vista de UnityPlayer:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) 
    if(mUnityPlayer.getParent() != null)
        ((ViewGroup)mUnityPlayer.getParent()).removeAllViews();
    
    view = inflater.inflate(R.layout.fragment_unity, container, false);
    this.frameLayoutForUnity = (FrameLayout) view.findViewById(R.id.unityFragmentLayout);
    this.frameLayoutForUnity.addView(mUnityPlayer.getView(),
            FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);

    mUnityPlayer.requestFocus();
    mUnityPlayer.windowFocusChanged(true);
    return view;

El resto sigue igual. Podría haber mejores soluciones que esa. Salud 🙂

nota: si aun no se resuelve tu pregunta por favor dejar un comentario y pronto lo podremos de nuevo , muchas gracias

por hoy,espero que te funcione

Deja una respuesta