Bir Android uygulamasını program aracılığıyla nasıl "yeniden başlatırım"?


231

İlk olarak, Android'de bir uygulamayı gerçekten öldürmemesi / yeniden başlatmaması gerektiğini biliyorum. Kullanım durumumda, sunucunun istemciye belirli bir bilgi gönderdiği belirli bir durumda uygulamamı fabrika ayarlarına sıfırlamak istiyorum.

Kullanıcı sunucuda yalnızca uygulamanın BİR örneği ile oturum açabilir (yani birden çok cihaza izin verilmez). Başka bir örnek "oturum açıldı" kilidini alırsa, tutarlılığı korumak için kullanıcının diğer tüm örneklerinin verilerini silmesi (fabrika ayarlarına sıfırlama) gerekir.

Kilidi zorla almak mümkündür, çünkü kullanıcı uygulamayı silebilir ve farklı bir örnek kimliğine neden olacak şekilde yeniden yükleyebilir ve kullanıcı kilidi artık serbest bırakamaz. Bu nedenle kilidi zorla almak mümkündür.

Bu güç olasılığı nedeniyle, somut bir durumda her zaman kilidinin olduğunu kontrol etmeliyiz. Bu sunucuya neredeyse her istek üzerine yapılır. Sunucu bir "yanlış kilit kimliği" gönderebilir. Bu tespit edilirse, istemci uygulamasının her şeyi silmesi gerekir.


Kullanım davası buydu.

Bir paylaşılanPrefs değerine bağlı olarak ActivityOturum Açma ActivityL veya uygulamanın ana ActivityB başlatan bir A var . L veya B'yi başlattıktan sonra kendini kapatır, böylece sadece L veya B çalışır. Yani kullanıcının giriş yapmış olması durumunda zaten B çalışıyor.

B C'yi başlatır. C D'yi çağırır startService.IntentService

(A)> B> C> D

OnHandleIntent D yönteminden ResultReceiver R'ye bir olay gönderilir.

R artık kullanıcıya uygulamayı fabrika ayarlarına sıfırlamayı (veritabanını silme, sharedPrefs, vb.) Seçebileceği bir iletişim kutusu sağlayarak bu olayı işler.

Sonra (bütün faaliyetleri kapatmak için) ve ancak o zaman giriş açılacağı tekrar A başlatmak uygulamayı yeniden başlatmak istiyorum fabrikada-reset ActivityL ve kendisini bitirir:

(A)> L

İletişim Kutusunun onClick yöntemi şuna benzer:

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

Ve bu MyAppsınıf:

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

Sorun FLAG_ACTIVITY_NEW_TASKB ve C Faaliyetleri kullanmak hala çalışıyor olmasıdır. Girişteki geri düğmesine basarsam ActivityC'yi görürüm, ancak ana ekrana geri dönmek istiyorum.

Eğer ben ayarlamazsanız FLAG_ACTIVITY_NEW_TASKhatayı alıyorum:

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?

Etkinlikler'i kullanamıyorum Context, çünkü ServiceIntentD, tarafından başlatılan bir arka plan görevinden de çağrılabilir AlarmManager.

Peki bunu (A)> L olan aktivite yığınına nasıl çözebilirim?

Yanıtlar:


284

Sen kullanabilirsiniz PendingIntentgelecekte başlangıç aktivitesinin başlatılması kurulumu ve sonra uygulamayı kapatmak

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
Bu benim için mükemmel çalıştı! Ben sadece android.os.Process.killProcess (android.os.Process.myPid ()) kullandım; System.exit () üzerinden;
FDIM

29
4.3 ve 4.4 cihazlarda (Test ettiğim her şey), bu, mevcut etkinliği öldürüyor ve daha sonra eskisinin üstünde yeni bir tane başlatıyor gibi görünüyor. Ben 2 aktiviteler derinim (ana -> tercihler). Geriye basmak beni eski uygulamaya, bir ekran geri götürüyor.
Mgamerz

5
Benim durumumda, bir işlem geri alındığı için System.exit (0) çalışmadı. Bunun yerine activity.finish (); ve gayet iyi çalışıyor.
Birleştir'me

6
@Qulin, çocuklar! Ciddi olamazsın! Bu örnek gerçek yaşam örneğinden çok yön gibidir. Bu snippet'i başlangıç ​​etkinliği adı, niyet kimliği ve çıkış mekaniği ile birlikte ne olursa olsun değiştirmeniz gerekir. Körü körüne kopyalayıp yapıştırmayın.
Oleg Koshkin

19
Arka plan etkinliklerine yönelik yeni kısıtlamalar nedeniyle Android Q ile bu artık çalışmıyor.android.com/preview/ privacy/…
Marco Righini

103

Sadece şunu arayabilirsiniz:

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

Kullanılan Hangi ProcessPhoenix kütüphanesinde


Alternatif olarak:

İşte @Oleg Koshkin cevabının biraz geliştirilmiş versiyonu.

Geçerli işlemin öldürülmesi de dahil olmak üzere etkinliğinizi gerçekten yeniden başlatmak istiyorsanız, kodu izlemeyi deneyin. Bir HelperClass'a veya ihtiyacınız olan yere yerleştirin.

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

Bu ayrıca jni sınıflarını ve tüm statik örnekleri yeniden başlatır.


1
Bu çözüm güzeldir, ancak 100 Millis'i azaltsanız bile uygulamanızı yeniden başlatana kadar birkaç saniye gecikecektir. Ancak, Jack Wharton tarafından bu kütüphane ProcessPhoenix daha iyi ve hızlı bir şekilde yapar, ancak uygulama içinde sadece bu işlev için kütüphane eklemeye değmez.
blueware

@blueware Cevabımı güncelledim ve ProcessPhonix içinde kullanılan kodu ekledim
mikepenz

mikepenz, bu adam "Ilya_Gazman" çok daha iyi ve böyle bir kütüphane kullanmadan yaptı.
blueware

3
@blueware - İlya'nın çözümü işlemi yeniden başlatmaz, bu nedenle statik veriler veya yüklü NDK kitaplıkları doğru şekilde yeniden başlatılmaz.
Ted Hopp

Bazı Huawei ve Samsung cihazları AlarmManagerbu çözümü kullanırken kısıtlamalara ve yanlış davranışlara sahiptir, Daha iyi bir yaklaşım var mı?
blueware

69

Jake Wharton kısa süre önce bunu güvenilir bir şekilde yapan ProcessPhoenix kütüphanesini yayınladı . Temel olarak sadece şunu aramanız gerekir:

ProcessPhoenix.triggerRebirth(context);

Kütüphane otomatik olarak çağrı etkinliğini bitirir, uygulama işlemini sonlandırır ve daha sonra varsayılan uygulama etkinliğini yeniden başlatır.


Bu işe yarıyor gibi görünüyor, ama (ki bildirilir) bir çökme olsun. Bunun ideal olduğundan emin değilim.
BK-

1
Lib ile hiç bir sorunum olmadı, ancak github.com/JakeWharton/ProcessPhoenix/issues
TBieniek 13:15

Argh, mesaja yeterince yakın bakmadığım için yorumumu geri çekiyorum. Varsayılan başlatma etkinliğimde bir niyet filtresi yoktu. Gereken kesin filtreleri belirtmek faydalı olabilir.
BK-

1
Bu şimdiye kadarki en iyi çözüm.
yongsunCN

1
@Shambhu, etiketi <category android:name="android.intent.category.DEFAULT" />uygulama bildiriminde <intent-filter> varsayılan etkinliğinize eklemeniz gerekir .
Muhammed Refaat

57

Ilya_Gazman yanıtını yeni API'ları kullanmak için biraz değiştirdim (IntentCompat, API 26'dan itibaren kullanımdan kaldırıldı). Runtime.getRuntime (). Exit (0), System.exit (0) 'dan daha iyi görünüyor.

 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
Doğrudan dokümanlardan : " Çağrı System.exit(n) etkili bir şekilde çağrıyla eşdeğerdir:Runtime.getRuntime().exit(n) ". Dahili olarak, System.exit()sadece döner ve arar Runtime.getRuntime().exit(). Biri veya diğeri hakkında "daha iyi" hiçbir şey yoktur (biri yazmanın ne kadar yazdığı veya fazladan bir yöntem çağrısı katmanı hakkında endişelenmedikçe).
Ted Hopp

nerede ve ne zaman yukarıdaki yöntem çağrısı?
Makvin

1
@ Nerede arayacağınıza karar verin. Benim durumum dil değişikliğinden sonra uygulamayı yeniden başlattı.
android_dev

@TedHopp her cevabı "iyi değil" olarak yorumluyor, uygulanabilir bir çözüm var mı? Alaycı olmamak, gerçekten bir iz bırakmadan bir uygulamayı yeniden oluşturmanız gerekir; statik değişkenlerden sınıf örneklerine.
Farid

1
@FARID - Çağrı Runtime.getRuntime().exit(0)(veya System.exit(0)) ile ilgili çözümlerden herhangi biri muhtemelen işe yarayacaktır. Bazı "iyi değil" yorumlarım cevaplar için ( Ilya Gazman'ın böyle bir çağrıyı içerecek şekilde düzenlendiği gibi)
Ted Hopp

37

IntentCompat.makeRestartActivityTask

Bunu yapmanın yeni yolu IntentCompat.makeRestartActivityTask kullanmaktır

Bir uygulamanın görevini temel durumunda yeniden başlatmak için kullanılabilecek bir Niyet yapın. Bu, makeMainActivity (ComponentName) gibidir, ancak Intent.FLAG_ACTIVITY_NEW_TASK ve FLAG_ACTIVITY_CLEAR_TASK bayraklarını da ayarlar.

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
Bu, görevi yeniden başlatır, ancak işlemi, hatta Applicationnesneyi yeniden başlatmaz . Bu nedenle , veya jni sınıflarının staticoluşturulması sırasında başlatılan tüm veriler, veriler Applicationgeçerli durumda kalır ve yeniden başlatılmaz .
Ted Hopp

2
@TedHopp Oh bu kısmı kaçırdım. System.exit (0) ekledim; Ama% 100 işe yarayacağından emin değilim. Daha sonra test
edeceğim

1
Bunu yapmak için açık kaynak kitaplığı kullanmadan en iyi çözüm. Eller yukarı ve bu yanıtı sağladığınız için teşekkürler, +1
blueware

4
Ne yazık ki, IntentCompat.makeRestartActivityTaskartık kullanımdan kaldırıldı . Eğer varsa kaynak kodlarını incelemek , basitçe bayrakları ekleme gibi basit olarak bulunuyor Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK.
Paul Lammertsma

IntentCompat.makeRestartActivityTask kaldırıldı
luckyhandler

28

Gerçekten güzel bir numara var. Benim sorunum, bazı gerçekten eski C ++ jni kitaplığı kaynakları sızdırılmış oldu. Bir noktada, çalışmayı durdurdu. Kullanıcı, uygulamadan çıkmaya ve tekrar başlatmaya çalıştı - sonuçsuz, çünkü bir etkinliği bitirmek işlemi bitirmek (veya öldürmek) ile aynı değildir. (Bu arada, kullanıcı çalışan uygulamalar listesine gidip oradan durdurabilir - bu işe yarardı, ancak kullanıcılar uygulamaları nasıl sonlandıracağını bilmiyorlar.)

Bu özelliğin etkisini gözlemlemek istiyorsanız static, etkinliğinize bir değişken ekleyin ve her birini artırın, örneğin düğmeye basın. Uygulama etkinliğinden çıkıp uygulamayı yeniden çağırırsanız, bu statik değişken değerini korur. (Uygulamadan gerçekten çıkılmışsa, değişkene başlangıç ​​değeri atanır.)

(Ve bunun yerine neden hatayı düzeltmek istemediğimi yorumlamak zorundayım . Kütüphane onlarca yıl önce yazılmış ve o zamandan beri kaynakları sızdırıyor. Yönetim her zaman işe yaradığına inanıyor . Geçici çözüm yerine bir düzeltme sağlama maliyeti ... Bence fikri anladın.)

Şimdi, jni paylaşılan (dinamik, .so) kitaplığını başlangıç ​​durumuna nasıl sıfırlayabilirim? Uygulamayı yeni bir işlem olarak yeniden başlatmayı seçtim.

İşin püf noktası, System.exit () öğesinin geçerli etkinliği kapatması ve Android'in uygulamayı daha az bir etkinlikle yeniden oluşturmasıdır.

Yani kod:

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

Çağıran aktivite sadece kodu çalıştırır MagicAppRestart.doRestart(this);, çağıran aktiviteonPause() yürütülür ve sonra işlem yeniden oluşturulur. Ve AndroidManifest.xml dosyasında bu etkinlikten bahsetmeyi unutmayın

Bu yöntemin avantajı, gecikme olmamasıdır.

UPD: Android 2.x'te çalıştı, ancak Android 4'te bir şey değişti.


3
etkinlik.startActivity (i) kullandım; System.exit (0); dahi çözümü
max4ever

5
Bu çözüm uygulamayı benim için kapatıyor, ancak yeniden başlamıyor. En azından Android 4.3'te.
Kirill Rakhman

1
Samsung galaxy mega android 4.2.2 üzerinde yeniden başlatma sonsuz döngü neden olur. Bu yüzden uygulama tekrar başlamayacak.
Günhan

@Gunhan 1) Değiştirmek ne olur System.exit(0)tarafından android.os.Process.killProcess(android.os.Process.myPid());? 2) Sonsuz bir döngü, bir uygulamayı yeniden başlattıklarında en üstteki etkinliği kaldırmadıkları anlamına gelir. Prensip olarak, statik bir boole değişkeni ekleyebilir, yeniden başlatma etkinliğini başlatmadan önce true olarak ayarlayabilirsiniz ve yeniden başlatmadan sonra yanlış olur. Böylece etkinlik, yeniden başlatmanın zaten olup olmadığını öğrenebilir (ve gerçekleşmişse, sadece bitir () ). OTOH, raporunuz, hilenin tüm cihazlarda aynı şekilde çalışmadığı anlamına gelir.
18446744073709551615

@Gunham Yeniden başlatmaya neden olan aynı etkinliği başlatıyorsanız, herhangi bir cihazda sonsuz döngü olacaktır.
Lukas Hanacek

23

Çözümüm işlemi / uygulamayı yeniden başlatmıyor. Yalnızca uygulamanın ev etkinliğini "yeniden başlatmasına" (ve diğer tüm etkinlikleri kapatmasına) izin verir. Kullanıcılar için yeniden başlatma gibi görünüyor, ancak işlem aynı. Sanırım bazı durumlarda insanlar bu etkiyi elde etmek istiyorlar, bu yüzden onu burada FYI olarak bırakıyorum.

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

15

Tamam, uygulamamı yeniden düzenledim ve A'yı otomatik olarak bitirmeyeceğim. Bunun her zaman çalışmasına izin verdim ve onActivityResultetkinlik boyunca bitirdim. Bu şekilde istediğimi elde etmek için FLAG_ACTIVITY_CLEAR_TOP+ FLAG_ACTIVITY_NEW_TASKbayraklarını kullanabilirim:

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

Ve içinde 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);
}

Yine de teşekkürler!


23
Bu olacak değil sınıfları oluşturmak yeniden sadece, uygulamayı yeniden başlatın. Böylece, sınıflar içindeki statik değişkenler önceki çalışmalardan değerleri koruyacaktır.
Brian White

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

24
Bu olacak değil sınıfları oluşturmak yeniden sadece, uygulamayı yeniden başlatın. Böylece, sınıflar içindeki statik değişkenler önceki çalışmalardan değerleri koruyacaktır.
Brian White

14

"Uygulamanız beklenmedik bir şekilde kapatıldı" seçeneğini tetiklemeyen tek kod aşağıdaki gibidir. Ayrıca harici bir kütüphane gerektirmeyen kullanımdan kaldırılmış bir koddur. Ayrıca bir zamanlayıcı gerektirmez.

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

Bunun API 29 ve sonraki sürümlerde çalıştığını gördüm - uygulamayı kullanıcı çalışmıyorken başlatmış gibi öldürmek ve yeniden başlatmak amacıyla.

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

Uygulamadaki başlatıcı etkinliği aşağıdakilere sahip olduğunda yapıldı:

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

Bir VARSAYILAN kategorisinin gerekli olduğunu iddia eden yorumlar gördüm, ancak böyle bir şey bulamadım. Uygulamamdaki Uygulama nesnesinin yeniden oluşturulduğunu doğruladım, bu yüzden sürecin gerçekten öldürüldüğüne ve yeniden başlatıldığına inanıyorum.

Bunu kullandığım tek amaç, kullanıcı Firebase Crashlytics için kilitlenme raporunu etkinleştirdikten veya devre dışı bıraktıktan sonra uygulamayı yeniden başlatmaktır. Dokümanlarına göre, bu değişikliğin geçerli olması için uygulamanın yeniden başlatılması (işlemin sonlandırılması ve yeniden oluşturulması) gerekir.


7

Bir uygulamayı tamamen yeniden başlatmanın en iyi yolu, FLAG_ACTIVITY_CLEAR_TOPve ile bir etkinliğe atlamak değil, uygulamayı yeniden başlatmaktır FLAG_ACTIVITY_NEW_TASK. Bu yüzden çözümüm bunu uygulamanızdan veya başka bir uygulamadan yapmaktır, tek koşul uygulama paketinin adını bilmektir (örnek: ' 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);
}

Kullanım yeniden başlatma veya fırlatma örneği Appa dan APPB :

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

Uygulamanın çalışıp çalışmadığını kontrol edebilirsiniz:

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

Not : Bu cevabın biraz konu dışı olduğunu biliyorum, ancak biri için gerçekten yararlı olabilir.


5

Yeniden başlatma uygulamaya Benim en iyi yolu kullanmaktır finishAffinity();
, yana finishAffinity();biz kullanabilmesi için, sadece Jelly Bean sürümlerinde kullanılabilirActivityCompat.finishAffinity(YourCurrentActivity.this); alt sürümleri için.

Sonra Intentilk etkinliği başlatmak için kullanın , böylece kod şöyle görünecektir:

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

Umarım yardımcı olur.


1
Bu, geçerli görevdeki tüm etkinlikleri sonlandırır, ancak işlemi yeniden başlatmaz ve hatta Application nesnesini yeniden oluşturmaz. Bu nedenle, Uygulamanın oluşturulması sırasında veya jni sınıfları tarafından başlatılan tüm statik veriler geçerli durumlarında kalır ve yeniden başlatılmaz.
Ted Hopp


3

PackageManager'ı kullanarak uygulamanızı genel bir şekilde yeniden başlatmak için bir örnek:

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

Bu görevi yeniden başlatır, ancak işlemi ve hatta Applicationnesneyi yeniden başlatmaz . Bu nedenle, statik veriler, Applicationveya jni sınıflarının oluşturulması sırasında başlatılan veriler geçerli durumlarında kalır ve yeniden başlatılmaz .
Ted Hopp

3

bunu dene:

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

1
Zaten aynı şeyi öneren diğer tüm cevaplarda olduğu gibi, bu uygulamayı yeniden başlatmaz, sadece sınıfları yeniden oluşturur. Bu nedenle, işlem içindeki statik veriler sıfırlanmaz.
Ted Hopp

2

Başlangıç ​​Ekranını FLAG_ACTIVITY_CLEAR_TASKve ile doğrudan başlatın FLAG_ACTIVITY_NEW_TASK.


2

Çıkışı geciktirmek için bir Handler eklemek zorunda kaldım:

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

2

kullanın:

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

API seviye 16 (4.1) 'den başlayarak çalıştığını düşünüyorum.


1

startInstrumentationYöntemini kullanabilirsiniz Activity. Boş Instrumentationve manifestte sivri uçlara ihtiyacınız var . Bundan sonra uygulamanızı yeniden başlatmak için bu yöntemi çağırabilirsiniz. Bunun gibi:

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 sınıf adını dinamik olarak alıyorum ama sabit kodlayabilirsiniz. Bunun gibi:

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

Çağrı startInstrumentationuygulamanızın yapmak yeniden. Bu yöntemin açıklamasını okuyun. Ancak öldürme uygulaması gibi davranıyorsa güvenli olmayabilir.


1

Üzerinde çalıştığım uygulama kullanıcıya hangi fragmanların görüntüleneceğini seçme imkanı vermek zorundadır (fragmanlar çalışma zamanında dinamik olarak değiştirilir). Benim için en iyi çözüm tamamen yeniden başlatmaktı , uygulamayı .

Bu yüzden birçok çözüm denedim ve hiçbiri benim için çalışmadı, ama bu:

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

Bunun bir başkasına yardım edeceğini umuyorum!


0

bunu dene:

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

İle Süreç Phoenix kütüphanesinde . Yeniden başlatmak istediğiniz Etkinlik "A" olarak adlandırılır.

Java lezzeti

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

Kotlin aroması

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

Bunun hata ayıklayıcının bağlantısını kesmenin talihsiz bir sonucu vardır.
DrSatan1

-3

Mevcut etkinliğinizi şu şekilde yeniden başlatabilirsiniz:

Fragman:

activity?.recreate()

Aktivite :

recreate()

3
OP'nin yapmak istediği bu değil.
Ted Hopp
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.