2010-04-21 16 views
65

En una aplicación de Android, usualmente recibimos el error "Force Closed" si no recibimos las excepciones correctas.Android: ¿Cómo reiniciar automáticamente la aplicación después de haber sido "forzada cerrada"?

¿Cómo puedo reiniciar mi aplicación automáticamente si se cierra forzosamente?

¿Se utiliza algún permiso específico para esto?

+4

Intente obtener las excepciones correctas.Una aplicación que se reinicia automáticamente puede ser molesta para los usuarios. –

+10

Solo quiero reiniciar mi aplicación si se cuelga. Creo que sería más amigable que molesto, especialmente cuando el usuario está en mi aplicación. Y sí, estoy tratando de obtener todas las excepciones correctas. :) – Johnny

+2

@Johnny: Por favor, comparta la solución para su problema. –

Respuesta

90

Para lograr esto hay que hacer dos cosas:

  1. evitar el "force close" - forma estándar de bloqueo de la aplicación.
  2. Configure un mecanismo de reinicio cuando ocurra el bloqueo de todos modos.

Véase más adelante cómo hacer esto:

  1. llamada Thread.setDefaultUncaughtExceptionHandler() con el fin de coger todos excepción no detectada, en el que será llamado método del caso uncaughtException(). "Force close" no aparecerá y la aplicación no responderá, lo cual no es algo bastante bueno. Con el fin de reiniciar la aplicación cuando se estrelló usted debe hacer lo siguiente:

  2. En el método onCreate, en su actividad inicializar un miembro de PendingIntent:

    Intent intent = PendingIntent.getActivity(
        YourApplication.getInstance().getBaseContext(), 
        0, 
        new Intent(getIntent()), 
        getIntent().getFlags()); 
    

continuación, poner el siguiente en uncaughtException() su método:

AlarmManager mgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE); 
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 2000, intent); 
System.exit(2); 

también debe llamar System.exit() De lo contrario, no funcionará. De esta forma, su aplicación se reiniciará después de 2 segundos.

Finalmente, puede establecer alguna bandera en su intento de que la aplicación se bloquee y en su método onCreate() puede mostrar un cuadro de diálogo "Lo siento, la aplicación se colgó, espero nunca más :)".

+3

Me di cuenta de eso. ahora el problema es dónde implementar el método uncaughtException? Por favor ayuda. Gracias. –

+1

@MayuMayooresan Puede extender la clase de aplicación o la Actividad y hacer lo siguiente en onCreate(): Thread.setDefaultUncaughtExceptionHandler (new UncaughtExceptionHandler() {...}); – AgentKnopf

+1

Si amplía la actividad, vale la pena señalar que debe hacer lo mismo para cada actividad que pueda actuar como punto de entrada para su aplicación (incluidas las que el sistema operativo Android puede decidir iniciar, por ejemplo, cuando muere una ventana, etc.) – Mick

15

El truco es asegurarse de que no se cierre forzosamente en primer lugar.

Si usa the Thread.setDefaultUncaughtExceptionHandler() method puede ver las excepciones que están causando que su aplicación se cierre forzosamente.

Eche un vistazo a at this question para ver un ejemplo del uso de UncaughtExceptionHandler para registrar las Excepciones planteadas por una aplicación.

+1

Gracias por la pista. Una pregunta de seguimiento es cuándo se llamaría a UncaughtExceptionHandler.uncaughtException? Si el usuario no hizo clic en el botón "Forzar cierre", ¿aún se llamará a UncaughtExceptionHandler.uncaughtException? – Johnny

+3

@Johnny Obtienes un cierre forzado cuando la aplicación genera una excepción que no se maneja. Si usa UncaughtExceptionHandler, su aplicación puede manejar todas sus Excepciones y el usuario nunca verá el diálogo Forzar cierre. En otras palabras, se llama al UncaughtExceptionHandler cuando se ha visualizado el cuadro de diálogo Forzar cierre. Sin embargo, deberá tener cuidado de cómo maneja cualquier excepción inesperada que su aplicación atrape; continuar y pretender que no pasó nada es obviamente arriesgado. –

+0

Gracias por la explicación. Explica bien sobre UncaughtExceptionHandler. Pero he visto aplicaciones que se reiniciarán automáticamente después del cierre forzado. P.ej. Iniciador (tal vez no es un buen ejemplo, pero he visto aplicaciones de terceros también funciona de esta manera). ¿Qué sucede si quiero que mi aplicación funcione así? ¿Tengo que usar algún tipo de permisos del sistema? – Johnny

2
public class ForceCloseExceptionHandalingActivity extends Activity { 
    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 
     setContentView(MyLayout()); 
     Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { 
      @Override 
      public void uncaughtException(Thread paramThread, Throwable paramThrowable) { 
       myHandaling(paramThread, paramThrowable); 
      } 
     }); 
    } 

    private ViewGroup MyLayout(){ 
     LinearLayout mainLayout = new LinearLayout(this); 
     mainLayout.setOrientation(LinearLayout.VERTICAL); 
     Button btnHello =new Button(this); 
     btnHello.setText("Show all button"); 
     btnHello.setOnClickListener(new OnClickListener() {   
      @Override 
      public void onClick(View v) {     
       setContentView(MyLayout2());    
      } 
     });    
     mainLayout.addView(btnHello);  
     return mainLayout; 
    } 

    private ViewGroup MyLayout2(){ 
     LinearLayout mainLayout = new LinearLayout(this); 
     mainLayout.setOrientation(LinearLayout.VERTICAL); 
     Button btnHello =new Button(this); 
     btnHello.setText("I am a EEROR uncaughtException"); 
     btnHello.setOnClickListener(new OnClickListener() {   
      @Override 
      public void onClick(View v) {     
       Log.e("Alert","btn uncaughtException::"); 
       Toast.makeText(ForceCloseExceptionHandalingActivity.this, "Alert uncaughtException222",Toast.LENGTH_LONG).show(); 
       View buttone = null; 
       setContentView(buttone);    
      } 
     });  
     Button btnHello2 =new Button(this); 
     btnHello2.setText("I am a EEROR Try n catch"); 
     btnHello2.setOnClickListener(new OnClickListener() {    
      @Override 
      public void onClick(View v) { 

       try{ 
        View buttone = null; 
        setContentView(buttone); 
       } 
       catch (Exception e) { 
        Log.e("Alert","Try n catch:::"); 
        Toast.makeText(ForceCloseExceptionHandalingActivity.this, "Alert Try n catch",Toast.LENGTH_LONG).show(); 
        setContentView(MyLayout()); 
       } 

      } 
     });  
     mainLayout.addView(btnHello); 
     mainLayout.addView(btnHello2); 
     return mainLayout; 
    } 
    public void myHandaling(Thread paramThread, Throwable paramThrowable){ 
     Log.e("Alert","Lets See if it Works !!!" +"paramThread:::" +paramThread +"paramThrowable:::" +paramThrowable); 
     Toast.makeText(ForceCloseExceptionHandalingActivity.this, "Alert uncaughtException111",Toast.LENGTH_LONG).show(); 
     Intent in =new Intent(ForceCloseExceptionHandalingActivity.this,com.satya.ForceCloseExceptionHandaling.ForceCloseExceptionHandalingActivity.class); 
     startActivity(in); 
     finish(); 
     android.os.Process.killProcess(android.os.Process.myPid()); 
    } 
    @Override 
    protected void onDestroy() { 
     Log.e("Alert","onDestroy:::"); 
     Toast.makeText(ForceCloseExceptionHandalingActivity.this, "Alert onDestroy",Toast.LENGTH_LONG).show(); 
     super.onDestroy(); 
    } 
+3

Demasiado detallado, poco claro. – greg7gkb

+0

este código obtiene el "Thread.setDefaultUncaughtExceptionHandler" y llama después de que se haya cerrado. – Satya

6

Si utiliza Crittercism o algún otro servicio de informe de errores, respuesta aceptada es casi justo ..

final UncaughtExceptionHandler defaultHandler = Thread.getDefaultUncaughtExceptionHandler(); 
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() { 
      public void uncaughtException(Thread thread, Throwable ex) { 
       Intent launchIntent = new Intent(activity().getIntent()); 
       PendingIntent pending = PendingIntent.getActivity(CSApplication.getContext(), 0, 
        launchIntent, activity().getIntent().getFlags()); 
       getAlarmManager().set(AlarmManager.RTC, System.currentTimeMillis() + 2000, pending); 
       defaultHandler.uncaughtException(thread, ex); 
      } 
}); 
0

Sólo añadir esta clase en su paquete

public class MyExceptionHandler implements 
    java.lang.Thread.UncaughtExceptionHandler { 
private final Context myContext; 
private final Class<?> myActivityClass; 

public MyExceptionHandler(Context context, Class<?> c) { 
    myContext = context; 
    myActivityClass = c; 
} 

public void uncaughtException(Thread thread, Throwable exception) { 
    StringWriter stackTrace = new StringWriter(); 
    exception.printStackTrace(new PrintWriter(stackTrace)); 
    System.err.println(stackTrace);// You can use LogCat too 
    Intent intent = new Intent(myContext, myActivityClass); 
    String s = stackTrace.toString(); 
    //you can use this String to know what caused the exception and in which Activity 
    intent.putExtra("uncaughtException", "Exception is: " + stackTrace.toString()); 
    intent.putExtra("stacktrace", s); 
    myContext.startActivity(intent); 
    //for restarting the Activity 
    Process.killProcess(Process.myPid()); 
    System.exit(0); 
}} 

Después, simplemente llame a:

Thread.setDefaultUncaughtExceptionHandler(new MyExceptionHandler(this, 
      SplashScreenActivity.class)); 
Cuestiones relacionadas