मैं एंड्रॉइड ऐप को प्रोग्रामेटिक रूप से "रीस्टार्ट" कैसे कर सकता हूं?


231

सबसे पहले, मुझे पता है कि किसी को एंड्रॉइड पर एप्लिकेशन को वास्तव में मारना / पुनः आरंभ नहीं करना चाहिए। मेरे उपयोग के मामले में मैं अपने आवेदन को एक विशिष्ट मामले में फ़ैक्टरी-रीसेट करना चाहता हूं जहां एक सर्वर क्लाइंट को एक विशिष्ट जानकारी भेजता है।

उपयोगकर्ता केवल एप्लिकेशन के एक उदाहरण (यानी कई उपकरणों की अनुमति नहीं है) के साथ सर्वर पर लॉग इन किया जा सकता है। यदि किसी अन्य उदाहरण में "लॉग-इन" -लॉक मिलता है, तो उस उपयोगकर्ता के अन्य सभी उदाहरणों को स्थिरता बनाए रखने के लिए अपने डेटा (फ़ैक्टरी-रीसेट) को हटाना होगा।

यह जबरन लॉक प्राप्त करने के लिए संभव है, क्योंकि उपयोगकर्ता ऐप को हटा सकता है और इसे फिर से इंस्टॉल कर सकता है जिसके परिणामस्वरूप एक अलग इंस्टेंस-आईडी होगा और उपयोगकर्ता लॉक को और अधिक मुक्त नहीं कर पाएगा। इसलिए जबरन ताला लगवाना संभव है।

उस बल-संभावना के कारण हमें हमेशा एक ठोस उदाहरण में जांचना होगा कि उसके पास ताला है। यह (लगभग) सर्वर पर प्रत्येक अनुरोध पर किया जाता है। सर्वर "गलत-लॉक-आईडी" भेज सकता है। यदि यह पता चला है, तो क्लाइंट एप्लिकेशन को सब कुछ हटाना होगा।


वह उपयोग-मामला था।

मेरे पास एक Activityए है जो एक साझाप्रेप्स मूल्य के आधार पर लॉगिन Activityएल या ऐप के मुख्य Activityबी को शुरू करता है। L या B शुरू करने के बाद यह अपने आप बंद हो जाता है ताकि केवल L या B चल रहा हो। तो इस मामले में कि उपयोगकर्ता पहले से ही लॉग इन है B अभी चल रहा है।

B, C. C startServiceको IntentServiceD. के लिए कॉल करना प्रारंभ करता है , जिसके परिणामस्वरूप इस स्टैक का परिणाम होता है:

(ए)> बी> सी> डी

D की एक घटना के onHandleIntent विधि से एक ResultReceiver R को भेज दिया जाता है ।

आर अब उस घटना को उपयोगकर्ता को एक संवाद प्रदान करके संभालता है, जहां वह एप्लिकेशन को फ़ैक्टरी-रीसेट करना (डेटाबेस को साझा करना, साझा करना, आदि) चुन सकता है)

फ़ैक्टरी-रीसेट के बाद मैं एप्लिकेशन को पुनरारंभ करना चाहता हूं (सभी गतिविधियों को बंद करने के लिए) और केवल ए को फिर से शुरू करें जो फिर लॉगिन Activityएल लॉन्च करता है और खुद को समाप्त करता है:

(ए)> एल

डायलॉग की ऑन -क्लिक विधि इस तरह दिखती है:

@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सी पर बैक बटन दबाता हूं, तो मैं होम स्क्रीन पर वापस जाना चाहता हूं।

यदि मैं सेट नहीं करता हूं तो 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, क्योंकि ServiceIntentडी को एक पृष्ठभूमि कार्य से भी बुलाया जा सकता है जिसे पृष्ठभूमि द्वारा शुरू किया गया है AlarmManager

तो मैं इसे (ए) एल बनने वाली गतिविधि स्टैक के लिए कैसे हल कर सकता हूं?

जवाबों:


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 () पर;
एफडीआईएम

29
4.3 और 4.4 डिवाइस पर (सभी मैंने परीक्षण किया है) यह वर्तमान गतिविधि को मारने और फिर पुराने एक के ऊपर एक नया लॉन्च करने के लिए लगता है। मैं 2 एक्टीविटीज़ डीप (मुख्य -> ​​प्रीफ़्स) हूं। वापस दबाने पर मुझे पुराने ऐप, एक स्क्रीन बैक में ले जाता है।
ममगर्ज़

5
मेरे मामले में, System.exit (0) एक लेनदेन के रूप में वापस काम नहीं कर रहा था। इसके बजाय मैंने गतिविधि का इस्तेमाल किया। फ़िनिश (); और यह ठीक काम करता है।
एकजुट हों

6
@Qulin, दोस्तों! आप गंभीर नहीं हो सकते! यह उदाहरण वास्तविक जीवन के उदाहरण से अधिक दिशा की तरह है। आपको इस स्निपेट को गतिविधि नाम, आशय आईडी, और जो कुछ भी आपके साथ हो यांत्रिकी से बाहर निकालना है। इसे आँख बंद करके पेस्ट न करें।
ओलेग कोस्किन

19
यह पृष्ठभूमि गतिविधियों के लिए नए प्रतिबंधों के कारण एंड्रॉइड क्यू के साथ अब काम नहीं करता है। डेवलपर
।android.com/preview/privacy/…

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 उत्तर का थोड़ा बेहतर संस्करण है।

यदि आप वास्तव में वर्तमान प्रक्रिया की मार सहित अपनी गतिविधि को फिर से शुरू करना चाहते हैं, तो कोड का प्रयास करें। इसे हेल्परक्लास में रखें या जहां आपको इसकी आवश्यकता हो।

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

इससे जेनी क्लासेस और सभी स्थिर उदाहरणों पर भी लगाम लगेगी।


1
यह समाधान अच्छा है, लेकिन यह कुछ सेकंड तक देरी करेगा जब तक कि यह आपके आवेदन को फिर से शुरू नहीं करता है, भले ही आपने 100 मिलिस कम किए हों। हालांकि, जैक व्हर्टन द्वारा यह लाइब्रेरी प्रोसेपोहेनिक्स बेहतर और जल्दी से करता है, लेकिन ऐप के अंदर केवल इस फ़ंक्शन के लिए पुस्तकालय जोड़ने के लायक नहीं है।
नीले रंग

@blueware मैंने अपना उत्तर अपडेट कर लिया है और कोड जोड़ा है जो
ProcessPhonix के

@mikepenz, इस लड़के "Ilya_Gazman" ने इस तरह के पुस्तकालय का उपयोग किए बिना बहुत बेहतर और बेहतर किया।
१२

3
@blueware - इल्या के समाधान को छोड़कर प्रक्रिया को फिर से शुरू नहीं किया जाएगा, इसलिए स्थैतिक डेटा या लोड एनडीके लाइब्रेरीज़ को सही ढंग से पुनर्निवेशित नहीं किया जाएगा।
टेड हॉप

कुछ Huawei और सैमसंग उपकरणों पर प्रतिबंध है AlarmManagerऔर इस समाधान का उपयोग करके गलत व्यवहार करते हैं, कोई बेहतर तरीका?
blueware

69

जेक व्हार्टन ने हाल ही में अपनी ProcessPhoenix लाइब्रेरी प्रकाशित की , जो यह एक विश्वसनीय तरीके से करता है। आपको मूल रूप से केवल कॉल करना है:

ProcessPhoenix.triggerRebirth(context);

पुस्तकालय स्वचालित रूप से कॉलिंग गतिविधि को समाप्त कर देगा, आवेदन प्रक्रिया को मार देगा और बाद में डिफ़ॉल्ट एप्लिकेशन गतिविधि को फिर से शुरू करेगा।


यह काम करने लगता है, लेकिन मुझे एक दुर्घटना (जो रिपोर्ट हो जाती है) मिलती है। यकीन नहीं होता कि यह आदर्श है।
BK-

1
मेरे पास कभी भी कोई समस्या नहीं थी, लेकिन मुझे लगता है कि github.com/JakeWharton/ProcessPhoenix/issues
मुनासिब है

अर्घ, मैं अपनी टिप्पणी को वापस लेता हूं क्योंकि मैंने संदेश को पर्याप्त रूप से नहीं देखा था। मुझे अपनी डिफ़ॉल्ट लॉन्च गतिविधि पर एक आशय फ़िल्टर याद आ रहा था। यह आवश्यक सटीक फ़िल्टर को ध्यान देने योग्य हो सकता है।
BK-

1
यह अब तक का सबसे अच्छा समाधान है।
yongsunCN

1
@ शंभू आपको ऐप <category android:name="android.intent.category.DEFAULT" />डिफॉल्ट में अपनी डिफ़ॉल्ट गतिविधि <आशय-फ़िल्टर> के लिए टैग जोड़ना होगा ।
मुहम्मद रिफैट

57

मैंने नए APIs का उपयोग करने के लिए Ilya_Gazman उत्तर को थोड़ा संशोधित किया है (IntentCompat शुरू किया गया API 26 है)। Runtime.getRuntime ()। Exit (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 का उपयोग करके है

एक ऐसी आशय बनाएं जिसका उपयोग किसी अनुप्रयोग के कार्य को उसके आधार स्थिति में पुन: लॉन्च करने के लिए किया जा सके। यह मेकमैनएक्टिविटी (कंपोनेंटनाम) की तरह है, लेकिन झंडे को भी सेट करता है। 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आरम्भिक डेटा या जेनी कक्षाएं उनके वर्तमान स्थिति में रहती हैं और उनका पुनर्निमाण नहीं किया जाता है।
टेड होप

2
@ टेडहॉप ओह मुझे वह हिस्सा याद आ गया। मैंने System.exit (0) को जोड़ा; लेकिन मुझे यकीन नहीं है कि 100% यह काम करेगा। मैं इसका बाद में परीक्षण करूंगा
इल्या गज़मैन

1
इसे करने के लिए ओपन सोर्स लाइब्रेरी का उपयोग किए बिना सबसे अच्छा समाधान। हाथ ऊपर करो और इस उत्तर को प्रदान करने के लिए धन्यवाद, +1
bluनर

4
दुर्भाग्य से, IntentCompat.makeRestartActivityTaskअब पदावनत कर दिया गया है । यदि आप स्रोत कोड का निरीक्षण करते हैं , तो यह केवल झंडे जोड़ने के समान सरल है Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK
पॉल लामर्ट्समा

IntentCompat.makeRestartActivityTask को हटा दिया गया
दिसंबर को भाग्यशाली

28

बहुत अच्छी चाल है। मेरी समस्या यह थी कि कुछ वास्तव में पुरानी सी ++ जेनी लाइब्रेरी ने संसाधनों को लीक कर दिया था। कुछ बिंदु पर, इसने कार्य करना बंद कर दिया। उपयोगकर्ता ने ऐप से बाहर निकलने और इसे फिर से लॉन्च करने की कोशिश की - बिना किसी परिणाम के, क्योंकि किसी गतिविधि को खत्म करना प्रक्रिया को खत्म करने (या मारने) के समान नहीं है। (वैसे, उपयोगकर्ता चल रहे एप्लिकेशनों की सूची में जा सकता है और इसे वहां से रोक सकता है - यह काम करेगा, लेकिन उपयोगकर्ता अभी यह नहीं जानते हैं कि अनुप्रयोगों को कैसे समाप्त किया जाए।)

यदि आप इस सुविधा के प्रभाव का निरीक्षण करना चाहते हैं, तो staticअपनी गतिविधि में एक चर जोड़ें और इसे बढ़ाएं, प्रत्येक, बटन दबाएं। यदि आप एप्लिकेशन गतिविधि से बाहर निकलते हैं और फिर आवेदन को फिर से शुरू करते हैं, तो यह स्थिर चर इसका मूल्य रखेगा। (यदि आवेदन वास्तव में बाहर हो गया था, तो चर को प्रारंभिक मूल्य सौंपा जाएगा।)

(और मुझे इस पर टिप्पणी करनी चाहिए कि मैं इसके बजाय बग को ठीक क्यों नहीं करना चाहता था । पुस्तकालय दशकों पहले लिखा गया था और संसाधनों को कभी लीक किया गया था। प्रबंधन का मानना ​​है कि यह हमेशा काम करता था । वर्कअराउंड के बजाय फिक्स प्रदान करने की लागत ... मुझे लगता है कि आपको विचार समझ आ गया है।)

अब, मैं प्रारंभिक अवस्था में साझा की गई (उर्फ डायनामिक, .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: यह एंड्रॉइड 2.x में काम करता था, लेकिन एंड्रॉइड 4 में कुछ बदल गया है।


3
मैंने गतिविधि का उपयोग किया था। स्टार्ट एक्टिविटी (i); System.exit (0); प्रतिभाशाली समाधान
अधिकतम

5
यह समाधान मेरे लिए ऐप को बंद कर देता है, लेकिन यह पुनः आरंभ नहीं करता है। कम से कम एंड्रॉइड 4.3 पर।
किरिल रहमान

1
सैमसंग गैलेक्सी मेगा एंड्रॉइड 4.2.2 पर यह पुनरारंभ के अनंत लूप का कारण बनता है। तो एप्लिकेशन फिर से शुरू नहीं होगा।
गुन्नन

@ गुंजन 1) यदि आप प्रतिस्थापित करते हैं तो क्या होता System.exit(0)है android.os.Process.killProcess(android.os.Process.myPid());? 2) एक अनंत लूप का सबसे अधिक संभावना है कि वे किसी ऐप को पुनरारंभ करने पर सबसे ऊपरी गतिविधि को नहीं हटाते हैं। सिद्धांत रूप में, आप एक स्थिर बूलियन चर जोड़ सकते हैं, पुनरारंभ गतिविधि को लागू करने से पहले इसे सही पर सेट करें, और पुनरारंभ होने के बाद यह गलत होगा। इस प्रकार गतिविधि यह पता लगा सकती है कि पुनरारंभ पहले ही हो चुका है या नहीं (और यदि ऐसा हुआ है, तो बस समाप्त () )। OTOH, आपकी रिपोर्ट का अर्थ है कि चाल सभी उपकरणों पर पहचान के अनुसार काम नहीं करती है।
18446744073709551615

@Gunham यदि आप वही गतिविधि शुरू कर रहे हैं जो पुनरारंभ हो रही है तो यह किसी भी डिवाइस पर अनंत लूप होगा।
लुकास हानसेक

23

मेरा समाधान प्रक्रिया / आवेदन को पुनः आरंभ नहीं करता है। यह केवल ऐप को घर की गतिविधि को "पुनरारंभ" करने देता है (और अन्य सभी गतिविधियों को खारिज करता है)। यह उपयोगकर्ताओं के लिए पुनरारंभ जैसा दिखता है, लेकिन प्रक्रिया समान है। मुझे लगता है कि कुछ मामलों में लोग इस प्रभाव को प्राप्त करना चाहते हैं, इसलिए मैं इसे यहां FYI करना छोड़ देता हूं।

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

15

ठीक है, मैंने अपना ऐप वापस कर दिया है और मैं अपने आप ए खत्म नहीं करूंगा। मैंने इसे हमेशा चलने दिया और 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

मैंने पाया है कि यह एपीआई 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 की एक श्रेणी की आवश्यकता है, लेकिन मुझे ऐसा नहीं मिला। मैंने पुष्टि की है कि मेरे ऐप में एप्लिकेशन ऑब्जेक्ट फिर से बनाया गया है, इसलिए मुझे विश्वास है कि प्रक्रिया वास्तव में मार दी गई है और फिर से शुरू हो गई है।

एकमात्र उद्देश्य जिसके लिए मैं इसका उपयोग करता हूं, उपयोगकर्ता द्वारा फायरबेस क्रैशशीटिक्स के लिए सक्षम या अक्षम क्रैश रिपोर्टिंग के बाद ऐप को पुनरारंभ करना है। उनके डॉक्स के अनुसार, परिवर्तन को प्रभावी करने के लिए ऐप को फिर से शुरू करना होगा (प्रक्रिया को मार दिया गया है और फिर से बनाया गया है)।


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

उपयोग पुनः आरंभ करने या प्रक्षेपण का उदाहरण अप्पा से 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();जेली बीन संस्करणों पर उपयोग किया जा सकता है, इसलिए हम 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
यह वर्तमान कार्य में सभी गतिविधियों को समाप्त करता है, लेकिन यह प्रक्रिया को पुनरारंभ नहीं करता है, या यहां तक ​​कि एप्लिकेशन ऑब्जेक्ट को फिर से बनाता है। इसलिए किसी भी स्थैतिक डेटा, अनुप्रयोग के निर्माण के दौरान या जेनी कक्षाओं द्वारा आरंभ किए गए डेटा, उनकी वर्तमान स्थिति में बने रहते हैं और वे पुन: स्थापित नहीं होते हैं।
टेड हॉप


3

यहां पैकेजमैनेजर का उपयोग करके अपने ऐप को सामान्य तरीके से पुनरारंभ करने का एक उदाहरण दिया गया है:

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

मुझे इंस्ट्रूमेंटेशन क्लास का नाम गतिशील रूप से मिलता है लेकिन आप इसे हार्डकोड कर सकते हैं। कुछ इस तरह:

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

कॉल करें startInstrumentationअपने ऐप का पुनः लोड करें। इस विधि का वर्णन पढ़ें। लेकिन किल ऐप की तरह काम करने पर यह सुरक्षित नहीं हो सकता।


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

फीनिक्स लाइब्रेरी प्रोसेस के साथ । जिस गतिविधि को आप फिर से शुरू करना चाहते हैं उसका नाम "ए" है।

जावा स्वाद

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

कोटलिन का स्वाद

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

यह आपके डिबगर डिस्कनेक्ट करने का दुर्भाग्यपूर्ण परिणाम है।
DrSatan1

-3

आप अपनी वर्तमान गतिविधि को इस तरह से फिर से शुरू कर सकते हैं:

टुकड़ा:

activity?.recreate()

गतिविधि:

recreate()

3
यह बिल्कुल नहीं है कि ओपी क्या करना चाहता है।
टेड हॉप
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.