Як я можу програмно "перезапустити" додаток для Android?


231

По-перше, я знаю, що дійсно не слід вбивати / перезапускати додаток на Android. У моєму випадку використання я хочу відновити заводські налаштування своєї програми в конкретному випадку, коли сервер надсилає клієнту конкретну інформацію.

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

Блокування можна примусово отримати, оскільки користувач може видалити додаток та перевстановити його, що призведе до іншого ідентифікатора інстанції, і користувач більше не зможе звільнити замок. Тому замок можна насильно дістати.

Через таку силу сили нам потрібно завжди перевіряти в конкретному випадку, що він має замок. Це робиться на (майже) кожному запиті до сервера. Сервер може надіслати "неправильний код блокування". Якщо це виявлено, клієнтська програма повинна все видалити.


Це був випадок використання.

У мене є ActivityA, який запускає ActivityL або вхід у систему ActivityB, залежно від значення sharedPrefs. Після запуску L або B він закривається таким чином, що працює тільки L або B. Так що у випадку, якщо користувач увійшов у систему вже працює B.

B починає дзвонити C. C startServiceдля IntentServiceD. Це результати в цьому стеку:

(A)> B> C> D

З методу onHandleIntent D подія надсилається ResultReceiver R.

R тепер обробляє цю подію, надаючи користувачеві діалогове вікно, де він може вибрати заводські скидання програми (видалити базу даних, sharedPrefs тощо)

Після скидання до заводських налаштувань я хочу перезапустити програму (закрити всі дії) і лише запустити A ще раз, який потім запустить логін ActivityL та завершить:

(A)> L

Метод onClick Dialog виглядає приблизно так:

@Override
public void onClick(DialogInterface dialog, int which) {

    // Will call onCancelListener
    MyApplication.factoryReset(); // (Deletes the database, clears sharedPrefs, etc.)
    Intent i = new Intent(MyApp.getContext(), A.class);
    i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    MyApp.getContext().startActivity(i);
}

І ось MyAppклас:

public class MyApp extends Application {
    private static Context context;

    @Override
    public void onCreate() {
        super.onCreate();
        context = getApplicationContext();
    }

    public static Context getContext() {
        return context;
    }

    public static void factoryReset() {
        // ...
    }
}

Проблема полягає в тому, якщо я використовую FLAG_ACTIVITY_NEW_TASKДіяння B і C, як і раніше, виконуються. Якщо я натиснув кнопку "Назад" на вході, Activityя побачу "C", але хочу повернутися на головний екран.

Якщо я не встановив, FLAG_ACTIVITY_NEW_TASKя отримаю помилку:

07-07 12:27:12.272: ERROR/AndroidRuntime(9512): android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity  context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?

Я не можу використовувати Діяльність ' Context, оскільки ServiceIntentD може бути викликаний також із фонового завдання, яке запускається AlarmManager.

Тож як я міг вирішити це, щоб стек активності став (A)> L?

Відповіді:


284

Ви можете використовувати PendingIntentдля налаштування запуску своєї діяльності в майбутньому, а потім закрити програму

Intent mStartActivity = new Intent(context, StartActivity.class);
int mPendingIntentId = 123456;
PendingIntent mPendingIntent = PendingIntent.getActivity(context, mPendingIntentId,    mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager mgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent);
System.exit(0);

5
Це прекрасно працювало для мене! Я щойно використовував android.os.Process.killProcess (android.os.Process.myPid ()); через System.exit ();
FDIM

29
На пристроях 4.3 та 4.4 (усе, що я перевірив) це, здається, знищує поточну активність, а потім запускає нову поверх верхньої частини старої. Я 2 активні глибокі (основні -> преф.). Якщо натиснути назад, я повертаюсь до старого додатка, один екран назад.
Mgamerz

5
У моєму випадку System.exit (0) не працював, оскільки транзакція поверталася назад. Натомість я використав Activity.finish (); і це працює чудово.
об’єднайте

6
@Qulin, хлопці! Ви не можете бути серйозними! Цей приклад більше схожий на напрямок, ніж на приклад із реального життя. Ви повинні змінити цей фрагмент із початковою назвою активності, ідентифікатором наміру та механікою виходу з будь-якого з них. Не слід копіювати його наосліп.
Олег Кошкін

19
Це більше не працює з Android Q через нові обмеження на фонову діяльність developer.android.com/preview/privacy/…
Marco Righini

103

Ви можете просто зателефонувати:

public static void triggerRebirth(Context context, Intent nextIntent) {
    Intent intent = new Intent(context, YourClass.class);
    intent.addFlags(FLAG_ACTIVITY_NEW_TASK);
    intent.putExtra(KEY_RESTART_INTENT, nextIntent);
    context.startActivity(intent);
    if (context instanceof Activity) {
      ((Activity) context).finish();
    }

    Runtime.getRuntime().exit(0);
}

Що використовується в бібліотеці ProcessPhoenix


Як альтернатива:

Ось трохи покращена версія відповіді @Oleg Koshkin.

Якщо ви дійсно хочете перезапустити свою діяльність, включаючи вбивство поточного процесу, спробуйте наступний код. Помістіть його в HelperClass або там, де вам це потрібно.

public static void doRestart(Context c) {
        try {
            //check if the context is given
            if (c != null) {
                //fetch the packagemanager so we can get the default launch activity 
                // (you can replace this intent with any other activity if you want
                PackageManager pm = c.getPackageManager();
                //check if we got the PackageManager
                if (pm != null) {
                    //create the intent with the default start activity for your application
                    Intent mStartActivity = pm.getLaunchIntentForPackage(
                            c.getPackageName()
                    );
                    if (mStartActivity != null) {
                        mStartActivity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                        //create a pending intent so the application is restarted after System.exit(0) was called. 
                        // We use an AlarmManager to call this intent in 100ms
                        int mPendingIntentId = 223344;
                        PendingIntent mPendingIntent = PendingIntent
                                .getActivity(c, mPendingIntentId, mStartActivity,
                                        PendingIntent.FLAG_CANCEL_CURRENT);
                        AlarmManager mgr = (AlarmManager) c.getSystemService(Context.ALARM_SERVICE);
                        mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent);
                        //kill the application
                        System.exit(0);
                    } else {
                        Log.e(TAG, "Was not able to restart application, mStartActivity null");
                    }
                } else {
                    Log.e(TAG, "Was not able to restart application, PM null");
                }
            } else {
                Log.e(TAG, "Was not able to restart application, Context null");
            }
        } catch (Exception ex) {
            Log.e(TAG, "Was not able to restart application");
        }
    }

Це також реініціалізує jni-класи та всі статичні екземпляри.


1
Це рішення добре, але воно затримається на кілька секунд, поки він не перезапустить додаток, навіть якщо ви зменшили 100 мільйонів. Однак ця бібліотека ProcessPhoenix від Джека Уортона робить це краще та швидше, але додавати бібліотеку лише для цієї функції всередині додатка не варто.
blueware

@blueware Я оновив свою відповідь і додав код, який використовується всередині ProcessPhonix
mikepenz

@mikepenz, цей хлопець "Ilya_Gazman" зробив набагато краще і без використання такої бібліотеки.
blueware

3
@blueware - За винятком того, що рішення Іллі не перезапустить процес, тому статичні дані або завантажені бібліотеки NDK не будуть правильно реанімізовані.
Тед Хопп

Деякі пристрої Huawei та Samsung мають обмеження AlarmManagerта неправильно поводяться при використанні цього рішення. Будь-який кращий підхід?
blueware

69

Нещодавно Джейк Уортон опублікував свою бібліотеку ProcessPhoenix , яка робить це надійно. Вам потрібно лише зателефонувати:

ProcessPhoenix.triggerRebirth(context);

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


Це, здається, працює, але я отримую збій (про який повідомляють). Не впевнений, що це ідеально.
BK-

1
У мене ніколи не було проблем із лібом, але сміливо
TBieniek

Аргу, я відкликав свій коментар, оскільки не переглядав повідомлення досить близько. У моїй активності запуску за замовчуванням у мене відсутній фільтр намірів. Можливо, варто відзначити необхідні точні фільтри намірів.
BK-

1
Це поки що найкраще рішення.
yongsunCN

1
@Shambhu ви повинні додати тег <category android:name="android.intent.category.DEFAULT" />до своєї активності <intent-filter> за замовчуванням у маніфесті програми.
Мухаммед Рефаат

57

Я трохи змінив відповідь Ilya_Gazman для використання нових API (IntentCompat застарілий, починаючи API 26). Runtime.getRuntime (). Вихід (0) здається кращим, ніж System.exit (0).

 public static void triggerRebirth(Context context) {
    PackageManager packageManager = context.getPackageManager();
    Intent intent = packageManager.getLaunchIntentForPackage(context.getPackageName());
    ComponentName componentName = intent.getComponent();
    Intent mainIntent = Intent.makeRestartActivityTask(componentName);
    context.startActivity(mainIntent);
    Runtime.getRuntime().exit(0);
}

8
Безпосередньо з документів : " Виклик System.exit(n) фактично еквівалентний виклику: Runtime.getRuntime().exit(n) ". Всередині System.exit()просто обертається і дзвонить Runtime.getRuntime().exit(). Немає нічого кращого в тому чи іншому (якщо когось не турбує те, скільки вводиться один чи про один додатковий шар викликів методу).
Тед Хопп

де і коли викликати вищевказаний метод?
Маквін

1
@Makvin ви вирішите, куди його зателефонувати. Мій випадок був перезавантажити додаток після зміни мови.
android_dev

@TedHopp коментує кожну відповідь як "не добре", чи є у вас якесь можливе рішення? Не будучи саркастичним, дійсно потрібно відтворити додаток без жодного сліду; від змінних статики до екземплярів класу.
Фарид

1
@FARID - Будь-яке рішення, яке передбачає виклик Runtime.getRuntime().exit(0)(або System.exit(0)), ймовірно, спрацює. Деякі мої "непогані" коментарі - це відповіді (як, наприклад, Ілля Газман , які з тих пір редагували, щоб включити такий дзвінок.
Тед Хопп

37

IntentCompat.makeRestartActivityTask

Новий спосіб зробити це за допомогою IntentCompat.makeRestartActivityTask

Зробіть наміри, які можна використовувати для повторного запуску завдання програми у його базовому стані. Це як makeMainActivity (ComponentName), але також встановлює прапорці Intent.FLAG_ACTIVITY_NEW_TASK та FLAG_ACTIVITY_CLEAR_TASK.

PackageManager packageManager = context.getPackageManager();
Intent intent = packageManager.getLaunchIntentForPackage(context.getPackageName());
ComponentName componentName = intent.getComponent();
Intent mainIntent = IntentCompat.makeRestartActivityTask(componentName);
context.startActivity(mainIntent);
System.exit(0);

6
Це відновить завдання, але воно не перезапускає процес або навіть Applicationоб'єкт. Тому будь-які staticдані, дані, ініціалізовані під час створення Applicationкласів, або jni, залишаються у їхньому поточному стані та не повторно ініціалізуються.
Тед Хопп

2
@TedHopp О, я пропустив цю частину. Я додав System.exit (0); Але я не впевнений на 100%, що це спрацює. Я перевіряю це останнє
Ілля Газман

1
Найкраще рішення без використання бібліотеки з відкритим кодом для цього. Руки вгору і спасибі за надану відповідь, +1
блюверр

4
На жаль, IntentCompat.makeRestartActivityTaskзараз застаріла . Якщо ви перевіряєте вихідний код , це так само просто, як просто додати прапори Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK.
Пол Ламмерцма

IntentCompat.makeRestartActivityTask вилучено
щасливчик

28

Є справді приємний трюк. Моя проблема полягала в тому, що деякі справді старі бібліотеки C ++ jni просочилися ресурси. У якийсь момент він перестав функціонувати. Користувач спробував вийти з програми та запустити його знову - безрезультатно, тому що закінчити діяльність - це не те саме, що закінчити (або вбити) процес. (До речі, користувач міг би перейти до списку запущених програм і зупинити його звідти - це спрацювало б, але користувачі просто не знають, як закінчити програми.)

Якщо ви хочете спостерігати за ефектом цієї функції, додайте staticзмінну до вашої діяльності та збільшуйте її, скажімо, кожне натискання кнопки. Якщо ви вийдете з активності програми та знову попросите її застосувати, ця статична змінна збереже своє значення. (Якщо програма дійсно була закрита, змінній буде призначено початкове значення.)

(І я повинен коментувати, чому я не хотів виправити помилку замість цього. Бібліотека була написана десятиліттями тому і витікала ресурси з тих пір. Керівництво вважає, що це завжди працювало . Вартість надання виправлення замість обходу ... Думаю, ви зрозуміли ідею.)

Тепер, як я можу відновити початкову бібліотеку jni-спільної (також динамічної, .so) бібліотеки? Я вирішив перезапустити програму як новий процес.

Хитрість полягає в тому, що System.exit () закриває поточну активність, а Android відтворює додаток на одну активність менше.

Отже код:

/** This activity shows nothing; instead, it restarts the android process */
public class MagicAppRestart extends Activity {
    // Do not forget to add it to AndroidManifest.xml
    // <activity android:name="your.package.name.MagicAppRestart"/>
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        System.exit(0);
    }
    public static void doRestart(Activity anyActivity) {
        anyActivity.startActivity(new Intent(anyActivity.getApplicationContext(), MagicAppRestart.class));
    }
}

Діяльність виклику просто виконує код MagicAppRestart.doRestart(this);, onPause()виконується активність виклику , а потім процес відновлюється. І не забудьте згадати цю діяльність в AndroidManifest.xml

Перевага цього методу в тому, що затримок немає.

UPD: він працював в Android 2.x, але в Android 4 щось змінилося.


3
я використав Activity.startActivity (i); System.exit (0); геніальне рішення
max4ever

5
Це рішення закриває додаток для мене, але воно не перезапускається. Принаймні, на Android 4.3.
Кирило Рахман

1
На samsung galaxy mega android 4.2.2 Це викликає нескінченний цикл перезавантаження. Тому додаток не запускається заново.
Гунхань

@Gunhan 1) що станеться, якщо замінити System.exit(0)на android.os.Process.killProcess(android.os.Process.myPid());? 2) нескінченний цикл, швидше за все, означає, що вони не видаляють найвищу активність під час перезавантаження програми. В принципі, ви можете додати статичну булеву змінну, встановити її як true перед викликом активності перезапуску, а після перезавантаження буде хибною. Таким чином, діяльність може з’ясувати, відбувся чи ні перезапуск (і якщо він стався, просто закінчіть () ). ОТО, ваш звіт означає, що фокус працює не однаково на всіх пристроях.
18446744073709551615

@Gunham Якщо ви починаєте ту саму діяльність, яка викликає перезапуск, це буде нескінченний цикл на будь-якому пристрої.
Лукаш Ханачек

23

Моє рішення не перезапускає процес / додаток. Це лише дозволяє додатку "перезапустити" домашню діяльність (і відмовитись від усіх інших заходів). Це виглядає як перезавантаження для користувачів, але процес той самий. Я думаю, що в деяких випадках люди хочуть досягти цього ефекту, тому я просто залишаю це FYI.

public void restart(){
    Intent intent = new Intent(this, YourHomeActivity.class);
    this.startActivity(intent);
    this.finishAffinity();
}

15

Гаразд, я відновив свою програму, і я не закінчу автоматично A. Я дозволяю цьому пробігу завжди і закінчую його через onActivityResultподію. Таким чином я можу використовувати прапори FLAG_ACTIVITY_CLEAR_TOP+, FLAG_ACTIVITY_NEW_TASKщоб отримати те, що я хочу:

public class A extends Activity {

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        finish();
    }

    protected void onResume() {
        super.onResume();
        // ...
        if (loggedIn) {
            startActivityForResult(new Intent(this, MainActivity.class), 0);
        } else {
            startActivityForResult(new Intent(this, LoginActivity.class), 0);
        }
    }
}

і в ResultReceiver

@Override
public void onClick(DialogInterface dialog, int which) {
    MyApp.factoryReset();
    Intent i = new Intent(MyApp.getContext(), A.class);
    i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    MyApp.getContext().startActivity(i);
}

Все одно, дякую!


23
Це не перезапустить додаток, лише заново створіть класи. Таким чином, будь-які статичні змінні в класах зберігатимуть значення попередніх циклів.
Брайан Уайт

14
Intent i = getBaseContext().getPackageManager().getLaunchIntentForPackage( getBaseContext().getPackageName() );
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);

24
Це не перезапустить додаток, лише заново створіть класи. Таким чином, будь-які статичні змінні в класах зберігатимуть значення попередніх циклів.
Брайан Вайт

14

Єдиний код, який не викликав "Ваш додаток несподівано закрився", полягає в наступному. Це також непридатний код, який не потребує зовнішньої бібліотеки. Також не потрібен таймер.

public static void triggerRebirth(Context context, Class myClass) {
    Intent intent = new Intent(context, myClass);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
    context.startActivity(intent);
    Runtime.getRuntime().exit(0);
}

8

Я виявив, що це працює в API 29 і пізніших версіях - з метою вбити та перезапустити додаток так, ніби користувач запустив його, коли він не працював.

public void restartApplication(final @NonNull Activity activity) {
   // Systems at 29/Q and later don't allow relaunch, but System.exit(0) on
   // all supported systems will relaunch ... but by killing the process, then
   // restarting the process with the back stack intact. We must make sure that
   // the launch activity is the only thing in the back stack before exiting.
   final PackageManager pm = activity.getPackageManager();
   final Intent intent = pm.getLaunchIntentForPackage(activity.getPackageName());
   activity.finishAffinity(); // Finishes all activities.
   activity.startActivity(intent);    // Start the launch activity
   System.exit(0);    // System finishes and automatically relaunches us.
}

Це було зроблено, коли активація запуску в додатку має таке:

<intent-filter>
    <action android:name="android.intent.action.VIEW"/>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

Я бачив коментарі, які стверджують, що потрібна категорія DEFAULT, але я не знайшов це так. Я підтвердив, що об’єкт Application в моєму додатку заново створений, тому вважаю, що процес справді був убитий і перезапущений.

Єдина мета, для якої я це використовую, - це перезапустити додаток після того, як користувач увімкнув або вимкнув звіт про аварійну ситуацію для Firebase Crashlytics. Відповідно до їхніх документів, додаток має бути перезапущено (процес знищено та заново створено), щоб ці зміни вступили в силу.


7

Найкращий спосіб повністю перезапустити додаток - це перезапустити його, а не просто перейти до активності з FLAG_ACTIVITY_CLEAR_TOPта FLAG_ACTIVITY_NEW_TASK. Тому моє рішення - зробити це з вашого додатка або навіть з іншого додатка, єдина умова - знати назву пакета програми (наприклад: ' com.example.myProject ')

 public static void forceRunApp(Context context, String packageApp){
    Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage(packageApp);
    launchIntent.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS | Intent.FLAG_ACTIVITY_NEW_TASK);
    context.startActivity(launchIntent);
}

Приклад перезапуску використання або запуску програмиA із appB :

forceRunApp(mContext, "com.example.myProject.appA");

Ви можете перевірити, чи працює програма:

 public static boolean isAppRunning(Context context, String packageApp){
    ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    List<ActivityManager.RunningAppProcessInfo> procInfos = activityManager.getRunningAppProcesses();
    for (int i = 0; i < procInfos.size(); i++) {
        if (procInfos.get(i).processName.equals(packageApp)) {
           return true;
        }
    }
    return false;
}

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


5

Мій найкращий спосіб перезапустити додаток - це використання, finishAffinity();
оскільки finishAffinity();його можна використовувати лише у версіях JELLY BEAN, тому ми можемо використовувати ActivityCompat.finishAffinity(YourCurrentActivity.this);для нижчих версій.

Потім використовуйте Intentдля запуску першої активності, так що код буде виглядати приблизно так:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
    finishAffinity();
    Intent intent = new Intent(getApplicationContext(), YourFirstActivity.class);
    startActivity(intent);
} else {
    ActivityCompat.finishAffinity(YourCurrentActivity.this);
    Intent intent = new Intent(getApplicationContext(), YourFirstActivity.class);
    startActivity(intent);
}

Сподіваюся, це допомагає.


1
Це закінчує всі дії в поточному завданні, але це не перезапускає процес і навіть не відтворює об’єкт Application. Тому будь-які статичні дані, дані, ініціалізовані під час створення Додатку, або класами jni, залишаються у своєму поточному стані та не повторно ініціалізуються.
Тед


3

Ось приклад перезапустити додаток загальним способом за допомогою PackageManager:

Intent i = getBaseContext().getPackageManager()
             .getLaunchIntentForPackage( getBaseContext().getPackageName() );
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);

Це відновить завдання, але воно не перезапускає процес або навіть Applicationоб'єкт. Тому будь-які статичні дані, дані, ініціалізовані під час створення Applicationкласів, або jni, залишаються у їхньому поточному стані та не повторно ініціалізуються.
Тед Хопп

3

спробуйте це:

Intent intent = getPackageManager().getLaunchIntentForPackage(getPackageName());
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

1
Як і у будь-якій іншій відповіді, яка вже пропонує те саме, це не перезапустить додаток, лише заново створить класи. Таким чином, будь-які статичні дані в процесі не будуть скинуті.
Тед Хопп

2

Безпосередньо запустіть початковий екран із FLAG_ACTIVITY_CLEAR_TASKта FLAG_ACTIVITY_NEW_TASK.


2

Мені довелося додати обробник, щоб затримати вихід:

 mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 200, mPendingIntent);
        final Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                Runtime.getRuntime().exit(0);
            }
        }, 100);


1

Ви можете використовувати startInstrumentationметод Activity. Вам потрібно виконати порожній Instrumentationта вказаний у маніфесті. Після цього ви можете викликати цей метод для перезавантаження програми. Подобається це:

try {           
    InstrumentationInfo info = getPackageManager().queryInstrumentation(getPackageName(), 0).get(0);
    ComponentName component = new ComponentName(this, Class.forName(info.name));
    startInstrumentation(component, null, null);
} catch (Throwable e) {             
    new RuntimeException("Failed restart with Instrumentation", e);
}

Я отримую ім'я класу Instrumentation динамічно, але ви можете його жорстко кодувати. Ось такі:

try {           
    startInstrumentation(new ComponentName(this, RebootInstrumentation.class), null, null); 
} catch (Throwable e) {             
    new RuntimeException("Failed restart with Instrumentation", e);
}

Зателефонуйте, startInstrumentationщоб перезавантажити додаток. Прочитайте опис цього методу. Але це не може бути безпечно, якщо діяти як програму kill.


1

Програма, над якою я працюю, повинна надавати користувачеві можливість вибирати фрагменти для відображення (фрагменти динамічно змінюються під час виконання). Найкращим рішенням для мене було повністю перезапустити програму.

Тому я спробував безліч рішень, і жодне з них не працювало на мене, але це:

final Intent mStartActivity = new Intent(SettingsActivity.this, Splash.class);
final int mPendingIntentId = 123456;
final PendingIntent mPendingIntent = PendingIntent.getActivity(SettingsActivity.this, mPendingIntentId, mStartActivity,
                    PendingIntent.FLAG_CANCEL_CURRENT);
final AlarmManager mgr = (AlarmManager) SettingsActivity.this.getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent);
this.finishAffinity(); //notice here
Runtime.getRuntime().exit(0); //notice here

Сподіваючись, що допоможе комусь іншому!


0

спробуйте це:

private void restartApp() {
    Intent intent = new Intent(getApplicationContext(), YourStarterActivity.class);
    int mPendingIntentId = MAGICAL_NUMBER;
    PendingIntent mPendingIntent = PendingIntent.getActivity(getApplicationContext(), mPendingIntentId, intent, PendingIntent.FLAG_CANCEL_CURRENT);
    AlarmManager mgr = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
    mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent);
    System.exit(0);
}

-1

З бібліотекою Process Phoenix . Діяльність, яку потрібно відновити, називається "A".

Ява смак

// Java
public void restart(){
    ProcessPhoenix.triggerRebirth(context);
}

Котлін аромат

// kotlin
fun restart() {
    ProcessPhoenix.triggerRebirth(context)
}

Це має невдалий результат відключення налагоджувача.
DrSatan1

-3

Ви можете перезапустити поточну діяльність так:

Фрагмент:

activity?.recreate()

Діяльність:

recreate()

3
Це зовсім не те, що хоче зробити ОП.
Тед Хопп
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.