Jak programowo „ponownie uruchomić” aplikację na Androida?

231

Po pierwsze wiem, że tak naprawdę nie należy zabijać / restartować aplikacji na Androidzie. W moim przypadku chcę przywrócić ustawienia fabryczne mojej aplikacji w konkretnym przypadku, w którym serwer wysyła określone informacje do klienta.

Użytkownik może być zalogowany tylko na serwerze z JEDNĄ instancją aplikacji (tzn. Wiele urządzeń nie jest dozwolonych). Jeśli inna instancja otrzyma tę blokadę „zalogowanego”, wówczas wszystkie inne instancje tego użytkownika muszą usunąć swoje dane (przywrócone do ustawień fabrycznych), aby zachować spójność.

Możliwe jest przymusowe uzyskanie blokady, ponieważ użytkownik może usunąć aplikację i zainstalować ją ponownie, co spowoduje inny identyfikator instancji, a użytkownik nie będzie już w stanie zwolnić blokady. Dlatego można siłą dostać blokadę.

Z powodu tej możliwości siły musimy zawsze sprawdzić w konkretnym przypadku, czy ma zamek. Odbywa się to (prawie) przy każdym żądaniu do serwera. Serwer może wysłać „błędny identyfikator blokady”. Jeśli zostanie wykryty, aplikacja kliencka musi usunąć wszystko.


To był przypadek użycia.

Mam ActivityA, który rozpoczyna logowanie ActivityL lub główny ActivityB aplikacji, w zależności od wartości sharedPrefs. Po uruchomieniu L lub B zamyka się tak, że działa tylko L lub B. Więc w przypadku, gdy użytkownik jest zalogowany, już działa B.

B uruchamia C. C wzywa startServicena IntentServiceD. To powoduje następujący stos:

(A)> B> C> D

Z metody onHandleIntent D zdarzenie jest wysyłane do ResultReceiver R.

R obsługuje teraz to zdarzenie, udostępniając użytkownikowi okno dialogowe, w którym może zresetować aplikację do ustawień fabrycznych (usunąć bazę danych, sharedPrefs itp.)

Po przywróceniu ustawień fabrycznych chcę ponownie uruchomić aplikację (aby zamknąć wszystkie działania) i uruchomić ponownie tylko A, który następnie uruchamia logowanie ActivityL i kończy się:

(A)> L

Metoda onClick okna dialogowego wygląda następująco:

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

I to jest MyAppklasa:

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() {
        // ...
    }
}

Problem polega na tym, że jeśli korzystam FLAG_ACTIVITY_NEW_TASKz działań B i C, nadal działają. Po naciśnięciu przycisku Wstecz przy logowaniu Activitywidzę C, ale chcę wrócić do ekranu głównego.

Jeśli nie ustawię FLAG_ACTIVITY_NEW_TASK, otrzymuję błąd:

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?

Nie mogę użyć działań ' Context, ponieważ ServiceIntentD może być również wywołane z zadania w tle, które jest uruchamiane przez AlarmManager.

Jak więc rozwiązać ten problem, zmieniając stos aktywności na (A)> L?

Oblepiony
źródło

Odpowiedzi:

284

Możesz użyć PendingIntent aby skonfigurować uruchamianie początkowej czynności w przyszłości, a następnie zamknąć aplikację

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);
Oleg Koshkin
źródło
5
To działało idealnie dla mnie! Właśnie użyłem android.os.Process.killProcess (android.os.Process.myPid ()); over System.exit ();
FDIM
29
Na urządzeniach 4.3 i 4.4 (wszystko, co przetestowałem) wydaje się, że zabija to bieżącą aktywność, a następnie uruchamia nowe nad starą. Mam 2 aktywności głębokie (główne -> preferencje). Naciśnięcie wstecz przenosi mnie do starej aplikacji, jeden ekran wstecz.
Mgamerz
5
W moim przypadku System.exit (0) nie działał, ponieważ transakcja była wycofywana. Zamiast tego użyłem activity.finish (); i działa dobrze.
zjednoczyć
6
@Qulin, chłopaki! Nie możesz mówić poważnie! Ten przykład bardziej przypomina kierunek niż przykład z życia. Musisz zmodyfikować ten fragment kodu, rozpoczynając od nazwy działania, identyfikatora zamiaru i mechaniki wyjścia bez względu na to, z czym korzystasz. Nie kopiuj go na ślepo.
Oleg Koshkin
19
To nie działa już z Androidem Q z powodu nowych ograniczeń działań w tle developer.android.com/preview/privacy/…
Marco Righini
103

Możesz po prostu zadzwonić:

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

Który jest używany w bibliotece ProcessPhoenix


Jako alternatywa:

Oto nieco ulepszona wersja odpowiedzi @Oleg Koshkin.

Jeśli naprawdę chcesz zrestartować swoją aktywność, w tym zabicie bieżącego procesu, spróbuj wykonać kod. Umieść go w HelperClass lub tam, gdzie jest to potrzebne.

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

Spowoduje to również ponowne zainicjowanie klas jni i wszystkich instancji statycznych.

mikepenz
źródło
1
To rozwiązanie jest dobre, ale opóźni się o kilka sekund, aż ponownie uruchomi aplikację, nawet jeśli zmniejszysz 100 Millis. Jednak ta biblioteka ProcessPhoenix autorstwa Jacka Whartona robi to lepiej i szybko, ale nie warto dodawać biblioteki tylko dla tej funkcji w aplikacji.
blueware
@blueware Zaktualizowałem swoją odpowiedź i dodałem kod używany w ProcessPhonix
mikepenz
@mikepenz, ten facet „Ilya_Gazman” radził sobie znacznie lepiej i bez korzystania z takiej biblioteki.
blueware,
3
@blueware - Z wyjątkiem tego, że rozwiązanie Ilyi nie uruchomi ponownie procesu, więc dane statyczne lub załadowane biblioteki NDK nie zostaną poprawnie ponownie zainicjowane.
Ted Hopp,
Niektóre urządzenia Huawei i Samsung mają ograniczenia AlarmManageri źle się zachowują, jeśli korzystają z tego rozwiązania. Czy jest jakieś lepsze podejście?
blueware
69

Jake Wharton niedawno opublikował swoją bibliotekę ProcessPhoenix , która robi to w niezawodny sposób. Zasadniczo wystarczy zadzwonić:

ProcessPhoenix.triggerRebirth(context);

Biblioteka automatycznie zakończy działanie wywołujące, zabije proces aplikacji i ponownie uruchomi domyślną aktywność aplikacji.

TBieniek
źródło
To wydaje się działać, ale dostaję awarię (która jest zgłaszana). Nie jestem pewien, czy to jest idealne.
BK-
1
Nigdy nie miałem żadnych problemów z lib, ale śmiało
mogę
Argh, wycofuję swój komentarz, ponieważ nie spojrzałem na wiadomość wystarczająco blisko. Brakowało mi filtru zamiarów w mojej domyślnej aktywności uruchamiania. Warto zwrócić uwagę na dokładne filtry zamiarów.
BK-
1
To jak dotąd najlepsze rozwiązanie.
yongsunCN,
1
@Shambhu musisz dodać tag <category android:name="android.intent.category.DEFAULT" />do domyślnej aktywności <intent-filter> w manifeście aplikacji.
Muhammed Refaat
57

Zmodyfikowałem nieco odpowiedź Ilya_Gazman, aby korzystać z nowych interfejsów API (IntentCompat jest przestarzały od API 26). Runtime.getRuntime (). Exit (0) wydaje się być lepsza niż 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);
}
android_dev
źródło
8
Bezpośrednio z dokumentacji : „ Połączenie System.exit(n) jest faktycznie równoważne z połączeniem: Runtime.getRuntime().exit(n) ”. Wewnętrznie System.exit()po prostu się odwraca i dzwoni Runtime.getRuntime().exit(). Nie ma nic „lepszego” w jednym lub drugim (chyba że ktoś jest zaniepokojony tym, jak dużo pisze się na maszynie lub jedną dodatkową warstwę wywołań metod).
Ted Hopp,
gdzie i kiedy wywołać powyższą metodę?
Makvin,
1
@ Makvin sam decydujesz, jak to nazwać. Mój przypadek został ponownie uruchomiony po zmianie języka.
android_dev
@TedHopp komentuje każdą odpowiedź jako „nie dobrą”, czy masz jakieś realne rozwiązanie? Nie będąc sarkastycznym, naprawdę trzeba odtworzyć aplikację bez śladu; od zmiennych statycznych do instancji klas.
Farid
1
@ FARID - Każde z rozwiązań wymagających połączenia Runtime.getRuntime().exit(0)(lub System.exit(0)) prawdopodobnie będzie działać. Niektóre z moich „niezbyt dobrych” komentarzy dotyczą odpowiedzi (takich jak Ilya Gazman , które zostały zredagowane w celu włączenia takiego wezwania.
Ted Hopp
37

IntentCompat.makeRestartActivityTask

Nowym sposobem na to jest użycie IntentCompat.makeRestartActivityTask

Wykonaj zamiar, którego można użyć do ponownego uruchomienia zadania aplikacji w stanie podstawowym. To jest jak makeMainActivity (ComponentName), ale ustawia także flagi Intent.FLAG_ACTIVITY_NEW_TASK i 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);
Ilya Gazman
źródło
6
Powoduje to ponowne uruchomienie zadania, ale nie powoduje ponownego uruchomienia procesu ani nawet Applicationobiektu. Dlatego wszelkie staticdane, dane zainicjowane podczas tworzenia Applicationklas lub klas jni pozostają w obecnym stanie i nie są ponownie inicjowane.
Ted Hopp
2
@TedHopp Och, tęskniłem za tą częścią. Dodałem System.exit (0); Ale nie jestem pewien w 100%, że to zadziała. Przetestuję to później
Ilya Gazman
1
Najlepsze rozwiązanie bez użycia biblioteki open source. Ręce do góry i dziękuję za udzielenie tej odpowiedzi, +1
blueware
4
Niestety IntentCompat.makeRestartActivityTaskjest teraz przestarzałe . Jeśli ty przejrzysz kod źródłowy , jest to tak proste, jak dodanie flag Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK.
Paul Lammertsma,
Usunięto IntentCompat.makeRestartActivityTask
luckyhandler
28

Jest naprawdę fajna sztuczka. Mój problem polegał na tym, że niektóre naprawdę stare biblioteki jni C ++ wyciekły z zasobów. W pewnym momencie przestał działać. Użytkownik próbował zamknąć aplikację i uruchomić ją ponownie - bez rezultatu, ponieważ zakończenie działania nie jest tym samym, co zakończenie (lub zabicie) procesu. (Nawiasem mówiąc, użytkownik może przejść do listy uruchomionych aplikacji i zatrzymać ją stamtąd - to zadziałałoby, ale użytkownicy po prostu nie wiedzą, jak zakończyć aplikacje.)

Jeśli chcesz obserwować efekt tej funkcji, dodaj staticzmienną do swojej aktywności i zwiększaj ją, powiedzmy, naciśnięcie przycisku. Jeśli zakończysz działanie aplikacji, a następnie uruchom ją ponownie, ta zmienna statyczna zachowa swoją wartość. (Jeśli aplikacja naprawdę została zakończona, zmienna otrzyma wartość początkową).

(I muszę skomentować, dlaczego zamiast tego nie chciałem naprawiać błędu. Biblioteka została napisana kilkadziesiąt lat temu i przeciekała zasoby od tego czasu. Zarząd uważa, że ​​zawsze działała . Koszt dostarczenia poprawki zamiast obejścia ... Myślę, że masz pomysł.)

Jak mogę zresetować bibliotekę współdzieloną jni (czyli dynamiczną, .so) do stanu początkowego? Zdecydowałem się zrestartować aplikację jako nowy proces.

Sztuka polega na tym, że System.exit () zamyka bieżącą aktywność, a Android odtwarza aplikację z jedną aktywnością mniejszą.

Więc kod to:

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

Działanie wywołujące po prostu wykonuje kod MagicAppRestart.doRestart(this);, działanie wywołujące onPause()jest wykonywane, a następnie proces jest odtwarzany ponownie. I nie zapomnij wspomnieć o tej aktywności w AndroidManifest.xml

Zaletą tej metody jest brak opóźnień.

UPD: działało w Androidzie 2.x, ale w Androidzie 4 coś się zmieniło.

18446744073709551615
źródło
3
użyłem działalności. startActivity (i); System.exit (0); genialne rozwiązanie
max4ever
5
To rozwiązanie zamyka dla mnie aplikację, ale nie uruchamia się ponownie. Przynajmniej na Androidzie 4.3.
Kirill Rakhman
1
Na Samsung Galaxy Mega Android 4.2.2 Powoduje nieskończoną pętlę restartu. Aplikacja nie uruchomi się ponownie.
Gunhan
@Gunhan 1) co się dzieje, jeśli zastąpić System.exit(0)przez android.os.Process.killProcess(android.os.Process.myPid());? 2) nieskończona pętla najprawdopodobniej oznacza, że ​​nie usuwają one najwyższej aktywności po ponownym uruchomieniu aplikacji. Zasadniczo można dodać statyczną zmienną logiczną, ustawić ją na true przed wywołaniem działania restartu, a po restarcie będzie to fałsz. W ten sposób aktywność może dowiedzieć się, czy restart już się odbył (a jeśli tak się stało, wystarczy zakończyć () ). OTOH, twój raport oznacza, że ​​sztuczka nie działa identycznie na wszystkich urządzeniach.
18446744073709551615
@Gunham Jeśli zaczynasz tę samą czynność, która powoduje ponowne uruchomienie, będzie to nieskończona pętla na dowolnym urządzeniu.
Lukas Hanacek
23

Moje rozwiązanie nie uruchamia ponownie procesu / aplikacji. Pozwala jedynie aplikacji „zrestartować” aktywność domową (i odrzucić wszystkie inne czynności). Dla użytkowników wygląda to na restart, ale proces jest taki sam. Myślę, że w niektórych przypadkach ludzie chcą osiągnąć ten efekt, więc zostawiam to tutaj FYI.

public void restart(){
    Intent intent = new Intent(this, YourHomeActivity.class);
    this.startActivity(intent);
    this.finishAffinity();
}
yongsunCN
źródło
15

Ok, zreorganizowałem moją aplikację i nie ukończę A automatycznie. Pozwoliłem, aby biegło to zawsze i kończę to onActivityResultwydarzenie. W ten sposób mogę użyć flag FLAG_ACTIVITY_CLEAR_TOP+, FLAG_ACTIVITY_NEW_TASKaby uzyskać to, czego chcę:

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

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

W każdym razie dzięki!

Oblepiony
źródło
23
Nie spowoduje to ponownego uruchomienia aplikacji, a jedynie ponowne utworzenie klas. Zatem wszelkie zmienne statyczne w ramach klas zachowają wartości z poprzednich przebiegów.
Brian White,
14
Intent i = getBaseContext().getPackageManager().getLaunchIntentForPackage( getBaseContext().getPackageName() );
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
Nirav Ranpara
źródło
24
Nie spowoduje to ponownego uruchomienia aplikacji, a jedynie ponowne utworzenie klas. Zatem wszelkie zmienne statyczne w ramach klas zachowają wartości z poprzednich przebiegów.
Brian White,
14

Jedyny kod, który nie uruchomił się „Twoja aplikacja została nieoczekiwanie zamknięta” to: Jest to również nieaktualny kod, który nie wymaga zewnętrznej biblioteki. Nie wymaga również timera.

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);
}
Haskell McRavin
źródło
8

Przekonałem się, że działa to na API 29 i późniejszych - w celu zabicia i ponownego uruchomienia aplikacji tak, jakby użytkownik uruchomił ją, gdy nie była uruchomiona.

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.
}

Stało się tak, gdy aktywność programu uruchamiającego w aplikacji ma następujące cechy:

<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>

Widziałem komentarze stwierdzające, że potrzebna jest kategoria DOMYŚLNA, ale nie znalazłem tego. Potwierdziłem, że obiekt Application w mojej aplikacji został ponownie utworzony, więc uważam, że proces naprawdę został zabity i ponownie uruchomiony.

Jedynym celem, z którego korzystam, jest ponowne uruchomienie aplikacji po tym, jak użytkownik włączy lub wyłączy raportowanie awarii Firebase Crashlytics. Zgodnie z ich dokumentami aplikacja musi zostać ponownie uruchomiona (proces zabity i ponownie utworzony), aby zmiana zaczęła obowiązywać.

Mark Peters
źródło
7

Najlepszym sposobem na pełne zrestartowanie aplikacji jest jej ponowne uruchomienie, a nie tylko przejście do aktywności za pomocą FLAG_ACTIVITY_CLEAR_TOPi FLAG_ACTIVITY_NEW_TASK. Więc moim rozwiązaniem jest zrobienie tego z Twojej aplikacji lub nawet z innej aplikacji, jedynym warunkiem jest znajomość nazwy pakietu aplikacji (przykład: „ 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);
}

Przykład ponownego uruchomienia lub uruchomienia aplikacji A z appB :

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

Możesz sprawdzić, czy aplikacja działa:

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

Uwaga : wiem, że ta odpowiedź jest nieco nie na temat, ale może być naprawdę pomocna dla kogoś.

Choletski
źródło
5

Moim najlepszym sposobem na ponowne uruchomienie aplikacji jest użycie finishAffinity();
Ponieważ, finishAffinity();można jej używać tylko w wersjach JELLY BEAN, więc możemy jej używaćActivityCompat.finishAffinity(YourCurrentActivity.this); przypadku niższych wersji.

Następnie użyj, Intentaby uruchomić pierwszą aktywność, aby kod wyglądał następująco:

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

Mam nadzieję, że to pomoże.

Hussein ND
źródło
1
To kończy wszystkie działania w bieżącym zadaniu, ale nie uruchamia ponownie procesu, ani nawet nie odtwarza obiektu aplikacji. Dlatego wszelkie dane statyczne, dane zainicjowane podczas tworzenia aplikacji lub klas jni pozostają w aktualnym stanie i nie są ponownie inicjowane.
Ted Hopp
3

Oto przykład ponownego uruchomienia aplikacji w ogólny sposób przy użyciu PackageManager:

Intent i = getBaseContext().getPackageManager()
             .getLaunchIntentForPackage( getBaseContext().getPackageName() );
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
Alireza Ghanbarinia
źródło
Powoduje to ponowne uruchomienie zadania, ale nie powoduje ponownego uruchomienia procesu ani nawet Applicationobiektu. Dlatego wszelkie dane statyczne, dane zainicjowane podczas tworzeniaApplication klas lub klas jni pozostają w bieżącym stanie i nie są ponownie inicjowane.
Ted Hopp
3

Spróbuj tego:

Intent intent = getPackageManager().getLaunchIntentForPackage(getPackageName());
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
veeson
źródło
1
Jak w przypadku każdej innej odpowiedzi już sugerującej to samo, nie spowoduje to ponownego uruchomienia aplikacji, a jedynie ponowne utworzenie klas. W związku z tym wszelkie dane statyczne w tym procesie nie zostaną zresetowane.
Ted Hopp
2

Bezpośrednio uruchom ekran początkowy za pomocą FLAG_ACTIVITY_CLEAR_TASKi FLAG_ACTIVITY_NEW_TASK.

Yijun Li
źródło
2

Musiałem dodać moduł obsługi, aby opóźnić wyjście:

 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);
Andy7229082
źródło
2

Posługiwać się:

navigateUpTo(new Intent(this, MainActivity.class));

Wierzę, że działa od poziomu API 16 (4.1).

Peter Mortensen
źródło
1

Możesz użyć startInstrumentationmetody Activity. Potrzebujesz implementacji pustej Instrumentationi wskazanej w manifeście. Następnie możesz wywołać tę metodę w celu ponownego uruchomienia aplikacji. Lubię to:

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

Nazwę klasy Instrumentation otrzymuję dynamicznie, ale możesz ją na stałe zakodować. Niektórzy lubią to:

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

Zadzwoń, startInstrumentationprzeładuj aplikację. Przeczytaj opis tej metody. Ale może to nie być bezpieczne, jeśli działa jak aplikacja typu kill.

Enyby
źródło
1

Aplikacja, nad którą pracuję, musi umożliwiać użytkownikowi wybór fragmentów do wyświetlenia (fragmenty są dynamicznie zmieniane w czasie wykonywania). Najlepszym rozwiązaniem dla mnie było całkowite ponowne uruchomienie aplikacji.

Wypróbowałem więc wiele rozwiązań i żadne z nich nie działało dla mnie, ale to:

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

Mam nadzieję, że pomoże to komuś innemu!

hzitoun
źródło
0

Spróbuj tego:

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);
}
Muhammad Mubeen
źródło
-1

Z biblioteką Process Phoenix . Działanie, które chcesz ponownie uruchomić, nosi nazwę „A”.

Smak Java

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

Smak Kotlina

// kotlin
fun restart() {
    ProcessPhoenix.triggerRebirth(context)
}
Raymond Chenon
źródło
Ma to niefortunny skutek powodujący rozłączenie się debugera.
DrSatan1
-3

Możesz ponownie uruchomić bieżącą aktywność w następujący sposób:

Fragment:

activity?.recreate()

Czynność :

recreate()

źródło
3
To nie jest wcale to, co OP chce zrobić.
Ted Hopp