Android: Wie starte ich eine Anwendung automatisch neu, nachdem sie zwangsweise geschlossen wurde?

81

In einer Android-Anwendung wurde normalerweise der Fehler "Force Closed" angezeigt, wenn die Ausnahmen nicht ordnungsgemäß behandelt wurden.

Wie kann ich meine Anwendung automatisch neu starten, wenn sie zwangsweise geschlossen wird?

Gibt es dafür eine spezielle Erlaubnis?

Johnny
quelle
5
Versuchen Sie, die Ausnahmen richtig zu machen. Eine Anwendung, die sich automatisch neu startet, kann für Benutzer ärgerlich sein.
Tomas Andrle
12
Ich möchte meine Anwendung nur neu starten, wenn sie abgestürzt ist. Ich denke, es wäre freundlicher als nervig, besonders wenn der Benutzer in meiner Anwendung ist. Und ja, ich versuche, jede Ausnahme richtig zu machen. :)
Johnny
2
@ Johnny: Bitte teilen Sie die Lösung für Ihr Problem.
Code_Life
Überprüfen Sie diesen Artikel , um Ihre Anwendung in einer Ausnahme neu zu starten.
Chintan Rathod

Antworten:

100

Um dies zu erreichen, müssen Sie zwei Dinge tun:

  1. Vermeiden Sie die "Force Close" - Standardmethode für Anwendungsabstürze.
  2. Richten Sie einen Neustartmechanismus ein, wenn der Absturz trotzdem auftritt.

Im Folgenden erfahren Sie, wie Sie dies tun:

  1. Rufen Sie Thread.setDefaultUncaughtExceptionHandler()auf, um alle nicht erfassten Ausnahmen abzufangen. In diesem Fall uncaughtException()wird die Methode aufgerufen. "Schließen schließen" wird nicht angezeigt und die Anwendung reagiert nicht, was nicht ganz gut ist. Um Ihre Anwendung beim Absturz neu zu starten, sollten Sie Folgendes tun:

  2. In der onCreateMethode initialisieren Sie in Ihrer Hauptaktivität ein PendingIntentMitglied:

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

Geben Sie dann Folgendes in Ihre uncaughtException()Methode ein:

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

Sie müssen auch anrufen System.exit(), sonst funktioniert nicht. Auf diese Weise wird Ihre Anwendung nach 2 Sekunden neu gestartet.

Schließlich können Sie ein Flag in Ihrer Absicht setzen, dass die Anwendung abgestürzt ist, und in Ihrer onCreate()Methode können Sie einen Dialog anzeigen "Es tut mir leid, die Anwendung ist abgestürzt, hoffe nie wieder :)".

Gyuri Majercsik
quelle
4
Ich habe das herausgefunden. Jetzt ist das Problem, wo uncaughtException-Methode zu implementieren? Bitte helfen Sie. Vielen Dank.
Jay Mayu
2
@MayuMayooresan Sie können entweder die Anwendungsklasse oder die Aktivität erweitern und in onCreate () Folgendes ausführen: Thread.setDefaultUncaughtExceptionHandler (neuer UncaughtExceptionHandler () {...});
AgentKnopf
1
Wenn Sie die Aktivität erweitern, ist es erwähnenswert, dass Sie dasselbe für jede Aktivität tun müssen, die als Einstiegspunkt für Ihre Anwendung dienen kann (einschließlich solcher, die Android OS möglicherweise starten möchte - zum Beispiel, wenn ein Fenster stirbt usw.)
Mick
1
Es scheint in ICS nicht zu funktionieren, nachdem der Prozess über das Menü "Apps verwalten" angehalten werden muss.
Sunghun
5
Was bedeutet YourApplication? Ich habe @ Mahesh-Ratschläge verwendet, aber es hat nicht funktioniert. bitte jemand erklärt es.
Shervin Gharib
16

Der Trick besteht darin, sicherzustellen, dass das Schließen nicht erzwungen wird.

Wenn Sie die Thread.setDefaultUncaughtExceptionHandler()Methode verwenden , können Sie die Ausnahmen abfangen, die dazu führen, dass Ihre Anwendung das Schließen erzwingt.

In dieser Frage finden Sie ein Beispiel für die Verwendung von a UncaughtExceptionHandlerzum Protokollieren der von einer Anwendung ausgelösten Ausnahmen.

Dave Webb
quelle
1
Danke für den Hinweis. Eine folgende Frage ist, wann die UncaughtExceptionHandler.uncaughtException aufgerufen wird. Wenn der Benutzer nicht auf die Schaltfläche "Schließen erzwingen" geklickt hat, wird die UncaughtExceptionHandler.uncaughtException weiterhin aufgerufen?
Johnny
3
@Johnny Sie erhalten ein Force Close, wenn die Anwendung eine Ausnahme auslöst, die nicht behandelt wird. Wenn Sie einen UncaughtExceptionHandler verwenden, kann Ihre Anwendung alle Ausnahmen verarbeiten, und der Benutzer wird das Dialogfeld "Schließen erzwingen" nie sehen. Mit anderen Worten, der UncaughtExceptionHandler wird aufgerufen, wenn das Dialogfeld "Schließen erzwingen" angezeigt worden wäre. Sie sollten jedoch vorsichtig sein, wie Sie mit unerwarteten Ausnahmen umgehen, die Ihre Anwendung abfängt. weiterzumachen und so zu tun, als wäre nichts passiert, ist offensichtlich riskant.
Dave Webb
Danke für die Erklärung. Es erklärt gut über den UncaughtExceptionHandler. Aber ich habe Anwendungen gesehen, die nach dem erzwungenen Schließen automatisch neu gestartet werden. Z.B. Launcher (vielleicht kein gutes Beispiel, aber ich habe gesehen, dass Apps von Drittanbietern auch so funktionieren). Was ist, wenn meine App so funktionieren soll? Muss ich Systemberechtigungen verwenden?
Johnny
10

Wenn Sie Crittercism oder einen anderen Fehlerbericht verwenden, ist die akzeptierte Antwort fast richtig.

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);
            }
});
Renetik
quelle
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();  
    }
Satya
quelle
Dieser Code erhält den "Thread.setDefaultUncaughtExceptionHandler" und ruft auf, nachdem er geschlossen wurde.
Satya
2

Fügen Sie diese Klasse einfach Ihrem Paket hinzu

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);
}}

Rufen Sie in Ihrer Anwendung oder in jeder Aktivitätsklasse innerhalb der onCreate () -Methode einfach Folgendes auf:

Thread.setDefaultUncaughtExceptionHandler(new MyExceptionHandler(this,
            SplashScreenActivity.class));
Suraj Vaishnav
quelle