Android: Làm thế nào để tự động khởi động lại một ứng dụng sau khi nó đã được "buộc đóng"?


81

Trong ứng dụng Android, chúng tôi thường gặp lỗi "Buộc đóng" nếu chúng tôi không xử lý các ngoại lệ đúng cách.

Làm cách nào để tôi có thể tự động khởi động lại ứng dụng của mình nếu nó bị đóng?

Có sự cho phép cụ thể nào được sử dụng cho việc này không?


5
Cố gắng làm đúng các ngoại lệ. Ứng dụng tự động khởi động lại có thể gây khó chịu cho người dùng.
Tomas Andrle

12
Tôi chỉ muốn khởi động lại ứng dụng của mình nếu nó bị lỗi. Tôi nghĩ nó sẽ thân thiện hơn là khó chịu, đặc biệt là khi người dùng đang ở trong ứng dụng của tôi. Và vâng, tôi đang cố gắng giải quyết mọi trường hợp ngoại lệ. :)
Johnny

2
@Johnny: Vui lòng chia sẻ giải pháp cho vấn đề của bạn.
Code_Life

kiểm tra bài viết này để khởi động lại ứng dụng của bạn trên bất kỳ trường hợp ngoại lệ nào.
Chintan Rathod

Câu trả lời:


100

Để đạt được điều này, bạn phải làm hai điều:

  1. Tránh "Buộc đóng" - cách tiêu chuẩn của sự cố ứng dụng.
  2. Thiết lập cơ chế khởi động lại khi sự cố vẫn xảy ra.

Xem bên dưới cách thực hiện những điều này:

  1. Gọi Thread.setDefaultUncaughtExceptionHandler()để bắt tất cả các ngoại lệ chưa được ghi, trong trường hợp đó uncaughtException()phương thức sẽ được gọi. "Buộc đóng" sẽ không xuất hiện và ứng dụng sẽ không phản hồi, đó không phải là một điều khá tốt. Để khởi động lại ứng dụng của bạn khi nó gặp sự cố, bạn nên làm như sau:

  2. Trong onCreatephương thức, trong hoạt động chính của bạn, hãy khởi tạo một PendingIntentthành viên:

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

Sau đó đặt những điều sau vào uncaughtException()phương pháp của bạn :

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

Bạn cũng phải gọi System.exit(), nếu không sẽ không hoạt động. Bằng cách này, ứng dụng của bạn sẽ khởi động lại sau 2 giây.

Cuối cùng, bạn có thể đặt một số cờ trong ý định của bạn rằng ứng dụng bị lỗi và trong onCreate()phương pháp của bạn, bạn có thể hiển thị hộp thoại "Tôi xin lỗi, ứng dụng bị lỗi, hy vọng không bao giờ xảy ra nữa :)".


4
Tôi đã tìm ra điều đó. bây giờ vấn đề là thực hiện phương thức uncaughtException ở đâu ?? làm ơn giúp đỡ. cảm ơn.
Jay Mayu

2
@MayuMayooresan Bạn có thể mở rộng lớp ứng dụng hoặc Activity và thực hiện như sau trong onCreate (): Thread.setDefaultUncaughtExceptionHandler (new UncaughtExceptionHandler () {...});
AgentKnopf

1
Nếu bạn mở rộng hoạt động, điều đáng chú ý là bạn cần thực hiện tương tự đối với mọi hoạt động có thể hoạt động như một điểm vào cho ứng dụng của bạn (bao gồm cả những hoạt động mà hệ điều hành Android có thể quyết định khởi động - ví dụ như khi cửa sổ chết, v.v.)
Mick

1
Nó dường như không hoạt động trong ICS sau khi buộc dừng quá trình thông qua menu quản lý ứng dụng.
sunghun

5
YourApplication có nghĩa là gì? Tôi đã sử dụng lời khuyên @Mahesh, nhưng nó không hiệu quả. xin ai đó giải thích nó.
Shervin Gharib

17

Bí quyết là hãy đảm bảo rằng nó không Buộc Đóng ngay từ đầu.

Nếu bạn sử dụng các Thread.setDefaultUncaughtExceptionHandler()phương pháp bạn có thể bắt các ngoại lệ đang gây ra ứng dụng của bạn để Force Close.

Hãy xem câu hỏi này để biết ví dụ về việc sử dụng UncaughtExceptionHandlerđể ghi lại các Ngoại lệ do một ứng dụng nêu ra.


1
Cảm ơn vì manh mối. Một câu hỏi tiếp theo là khi nào thì UncaughtExceptionHandler.uncaughtException sẽ được gọi? Nếu người dùng không nhấp vào nút "Buộc đóng", liệu UncaughtExceptionHandler.uncaughtException có còn được gọi không?
Johnny

3
@Johnny Bạn nhận được Force Close khi ứng dụng đưa ra một Ngoại lệ không được xử lý. Nếu bạn sử dụng UncaughtExceptionHandler thì ứng dụng của bạn có thể xử lý tất cả các Ngoại lệ của nó và người dùng sẽ không bao giờ thấy hộp thoại Buộc đóng. Nói cách khác, UncaughtExceptionHandler được gọi khi hộp thoại Force Close được hiển thị. Tuy nhiên, bạn sẽ muốn cẩn thận cách xử lý bất kỳ Ngoại lệ bất ngờ nào mà ứng dụng của bạn bắt gặp; tiếp tục và giả vờ như không có gì xảy ra rõ ràng là rủi ro.
Dave Webb

Cảm ơn vì lời giải thích. Nó giải thích tốt về UncaughtExceptionHandler. Nhưng tôi đã thấy các ứng dụng sẽ tự động khởi động lại sau khi bị đóng. Ví dụ. Trình khởi chạy (có thể không phải là một ví dụ điển hình, nhưng tôi đã thấy các ứng dụng của bên thứ ba cũng hoạt động theo cách này). Điều gì xảy ra nếu tôi muốn ứng dụng của mình hoạt động như thế này? Tôi có phải sử dụng một số loại quyền hệ thống không?
Johnny

10

Nếu bạn sử dụng Crittercism hoặc một số dịch vụ báo lỗi khác, câu trả lời được chấp nhận là gần như đúng ..

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

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

mã này nhận được "Thread.setDefaultUncaughtExceptionHandler" và gọi sau khi nó đã được đóng ..
Satya

2

Chỉ cần thêm lớp này vào gói của bạn

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

Trong ứng dụng của bạn hoặc trong mọi lớp hoạt động, bên trong phương thức onCreate () sau đó chỉ cần gọi:

Thread.setDefaultUncaughtExceptionHandler(new MyExceptionHandler(this,
            SplashScreenActivity.class));
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.