दिलचस्प पोस्ट
शुरुआती के लिए गिट: निश्चित व्यावहारिक गाइड Google Play सेवाओं के साथ एंड्रॉइड स्टूडियो खोजदृश्य विजेट की पृष्ठभूमि को बदलने योग्य बनाना दृश्य स्टूडियो में "stdafx.h" के लिए क्या उपयोग है? इंटेल सिंटैक्स में विधानसभा कोड उत्पन्न करने के लिए आप जीसीसी का उपयोग कैसे करते हैं? । htaccess: अमान्य कमांड 'रीवरइटइंजिन', संभवतः गलत वर्तनी या परिभाषित किया गया एक मॉड्यूल जो सर्वर कॉन्फ़िगरेशन में शामिल नहीं है कैसे RecyclerView में आइटम के बीच डिवाइडर और रिक्त स्थान जोड़ने के लिए? कन्स्ट्रक्टर के अंदर आभासी फ़ंक्शन कॉल करना आईओएस में वर्तमान डिवाइस भाषा प्राप्त करना? जावा में टॉस्ट्रिंग विधि एक सरणी के लिए काम क्यों नहीं करती? सिस्टम। विन्डोज। थ्रेडिंग। डिस्पार्चर और विनफॉर्म? क्या Google प्रपत्र से डेटा का उपयोग करते हुए एक Google फ़ॉर्म 'प्रीफिल' करना संभव है? jQuery डिफर्ड – खत्म करने के लिए एकाधिक AJAX अनुरोधों की प्रतीक्षा कर रहा है किसी पाठ फ़ाइल में पंक्तियां हटाएं जिसमें कोई विशिष्ट स्ट्रिंग हो मुझे नए कीवर्ड को C ++ में कब उपयोग करना चाहिए?

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

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

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

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

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


यही प्रयोग-केस था। कार्यान्वयन-प्रश्न के लिए नहीं:

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

बी शुरू होता है सी। सी शुरू IntentService डी। जो इस स्टैक में परिणाम:

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

डी की ऑनहैंड ईंटेंट विधि से एक इवेंट को रिजल्ट रीसेवर आर को भेज दिया जाता है।

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

फ़ैक्टरी-रीसेट के बाद मैं आवेदन को पुनरारंभ करना चाहता हूं (सभी गतिविधियों को बंद करने के लिए) और केवल एक फिर से शुरू करें जो फिर लॉगिन 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 का उपयोग करते FLAG_ACTIVITY_NEW_TASK तो क्रियाएँ बी और सी अभी भी चल रहे हैं अगर मैं लॉगिन 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 डी को पृष्ठभूमि पृष्ठभूमि से भी कहा जा सकता है जो ServiceIntent द्वारा शुरू किया गया है।

तो मैं यह कैसे गतिविधि स्टैक (ए)> एल बनने के लिए हल कर सकते हैं?

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

आप भविष्य में अपनी प्रारंभिक गतिविधि लॉन्च करने के लिए 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); 

आप बस कॉल कर सकते हैं:

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

प्रोसेफफिएनिक्स लाइब्रेरी में इसका इस्तेमाल किया जाता है


विकल्प के रूप में:

@ ऑलेग काशकिन उत्तर का थोड़ा बेहतर संस्करण यहां है

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

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

यह भी जेनी वर्गों और सभी स्थैतिक उदाहरणों को पुनः आरंभ करेगा।

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

 ProcessPhoenix.triggerRebirth(context); 

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

IntentCompat.makeRestartActivityTask

ऐसा करने का नया तरीका, IntentCompat.makeRestartActivityTask का उपयोग कर रहा है

किसी आशय का प्रयोग करें जिसका इस्तेमाल उसके आधार राज्य में किसी एप्लिकेशन के कार्य को पुन: लॉन्च करने के लिए किया जा सकता है। यह मेकॅनिएक्टिविटी (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); 

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

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

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

अब, मैं आरंभिक स्थिति में जीनी कैसे साझा कर सकता हूं (उर्फ गतिशील, .so) पुस्तकालय? मैंने एक नई प्रक्रिया के रूप में आवेदन को फिर से शुरू करना चुना है

चाल यही है कि System.exit () वर्तमान गतिविधि को बंद कर देता है और एंड्रॉइड एप्लिकेशन को एक गतिविधि के साथ कम करता है।

तो कोड है:

 /** 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 में कुछ बदल गया है।

ठीक है, मैंने अपना ऐप पुन: सुधार किया और मैं एक स्वचालित रूप से समाप्त नहीं करूँगा मैं इस दौड़ को हमेशा चलो और इसे 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); } 

फिर भी धन्यवाद!

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

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

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

किसी ऐप को पूरी तरह से पुन: प्रारंभ करने का सबसे अच्छा तरीका यह पुन: लॉन्च करना है, न कि केवल 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; } 

नोट : मुझे पता है कि यह जवाब विषय से थोड़ा सा है, लेकिन यह किसी के लिए वास्तव में उपयोगी हो सकता है

FLAG_ACTIVITY_CLEAR_TASK का उपयोग करने का प्रयास करें

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

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

सीधे प्रारंभिक स्क्रीन को FLAG_ACTIVITY_CLEAR_TASK और FLAG_ACTIVITY_NEW_TASK साथ प्रारंभ करें

बाहर निकलने में देरी करने के लिए मुझे एक हेन्डलर जोड़ना था:

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

मैंने नए एपीआई का इस्तेमाल करने के लिए इल्या_जीज़मैन के जवाब में थोड़ा बदलाव किया है (इंटेंटकंपप एपीआई 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); } 

आप Activity की startInstrumentation विधि का उपयोग कर सकते हैं। आपको खाली 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 अपने ऐप का पुनः लोड करें इस विधि का विवरण पढ़ें लेकिन मारना ऐप की तरह अभिनय करना सुरक्षित नहीं हो सकता

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

तो मैंने बहुत सारे समाधान किए, और उनमें से कोई भी मेरे लिए काम नहीं कर रहा है, लेकिन यह:

 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 

उम्मीद है कि किसी और की मदद करने वाला है!

उपयोग:

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

यह एपीआई स्तर 16 (4.1) से शुरू होता है, मेरा मानना ​​है कि

इसे इस्तेमाल करे:

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