Android: Як автоматично перезапустити програму після її “примусового закриття”?


81

У програмі для Android ми зазвичай отримуємо помилку "Примусово закрити", якщо не працювали з винятками належним чином.

Як я можу перезапустити свою програму автоматично, якщо вона примусово закрита?

Чи для цього використовується якийсь конкретний дозвіл?


5
Спробуйте виправити винятки. Додаток, який автоматично перезапускається, може дратувати користувачів.
Томас Андрле,

12
Я просто хочу перезапустити свою програму, якщо вона вийшла з ладу. Я думаю, це було б більше дружньо, ніж дратувати, особливо коли користувач знаходиться у моєму додатку. І так, я намагаюся виправити всі винятки. :)
Джонні,

2
@Johnny: Будь ласка, поділіться рішенням вашої проблеми.
Code_Life

перегляньте цю статтю, щоб перезапустити програму щодо будь-якого виключення.
Чінтан Ратод

Відповіді:


100

Для цього потрібно зробити дві речі:

  1. Уникайте "Примусового закриття" - стандартного способу збою програми.
  2. Налаштуйте механізм перезапуску, коли аварія все одно трапиться.

Подивіться нижче, як це зробити:

  1. Зателефонуйте Thread.setDefaultUncaughtExceptionHandler(), щоб уловити всі невпіймані винятки, і в цьому випадку uncaughtException()буде викликаний метод. "Примусове закриття" не з'явиться, і програма не відповідатиме, що не зовсім добре. Для того, щоб перезапустити програму, коли вона вийшла з ладу, вам слід зробити наступне:

  2. У onCreateметоді у вашій основній діяльності ініціалізуйте PendingIntentучасника:

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

Потім додайте у свій uncaughtException()метод наступне :

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

Ви також повинні зателефонувати System.exit(), інакше не вийде. Таким чином, ваша програма перезапуститься через 2 секунди.

Врешті-решт ви можете встановити прапор у своєму намірі, що програма розбилася, а у вашому onCreate()методі ви можете показати діалогове вікно "Вибачте, програма розбилася, сподіваюся ніколи більше :)".


4
Я це зрозумів. тепер проблема в тому, де реалізувати метод uncaughtException ?? плз допомога. Дякую.
Jay Mayu

2
@MayuMayooresan Ви можете або розширити клас програми або Activity і виконати наступне в onCreate (): Thread.setDefaultUncaughtExceptionHandler (new UncaughtExceptionHandler () {...});
AgentKnopf,

1
Якщо ви продовжуєте діяльність, варто зазначити, що вам потрібно робити те саме для кожної діяльності, яка може виступати точкою входу для вашої програми (включаючи ті, які ОС Android може вирішити запустити - наприклад, коли вікно вмирає тощо)
Мік

1
Здається, це не працює в ICS після змушення зупинити процес через меню керування програмами.
sunghun

5
що означає YourApplication? Я користувався порадою @Mahesh, але це не спрацювало. будь ласка, хтось пояснить це.
Шервін Гаріб

16

Фокус у тому, щоб спочатку переконатися, що він не змушує закривати.

Якщо ви використовуєте в Thread.setDefaultUncaughtExceptionHandler()метод ви можете зловити винятку, які викликають додаток до Force Close.

Погляньте на це запитання для прикладу використання UncaughtExceptionHandlerжурналу винятків, викликаних додатком.


1
Дякую за підказку. Наступне питання - коли буде викликано UncaughtExceptionHandler.uncaughtException? Якщо користувач не натиснув кнопку "Примусово закрити", чи буде все-таки викликано UncaughtExceptionHandler.uncaughtException?
Джонні,

3
@Johnny Ви отримуєте Force Close, коли програма викликає виняток, який не обробляється. Якщо ви використовуєте UncaughtExceptionHandler, тоді ваша програма може обробляти всі її винятки, і користувач ніколи не побачить діалогове вікно Примусове закриття. Іншими словами, UncaughtExceptionHandler викликається, коли було б відображено діалогове вікно Примусове закриття. Однак ви хочете бути обережними, як ви обробляєте будь-які несподівані винятки, які вловлює ваш додаток; продовжувати і робити вигляд, що нічого не сталося - очевидно ризиковано.
Дейв Вебб,

Дякую за пояснення. Це добре пояснює про UncaughtExceptionHandler. Але я бачив програми, які автоматично перезапускатимуться після примусового закриття. Напр. Launcher (можливо, це не гарний приклад, але я бачив, що сторонні програми працюють і таким чином). Що робити, якщо я хочу, щоб моя програма працювала так? Чи повинен я використовувати якісь системні дозволи?
Джонні,

10

Якщо ви використовуєте "Критицизм" або якусь іншу службу повідомлення про помилки, прийнята відповідь майже правильна.

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

цей код отримує "Thread.setDefaultUncaughtExceptionHandler" і дзвонить після його закриття ..
Satya

2

Просто додайте цей клас у свій пакет

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

У вашому додатку або в кожному класі діяльності всередині методу onCreate () просто викличте:

Thread.setDefaultUncaughtExceptionHandler(new MyExceptionHandler(this,
            SplashScreenActivity.class));
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.