আমি কীভাবে প্রোগ্রামে কোনও অ্যান্ড্রয়েড অ্যাপ্লিকেশনটিকে "পুনঃসূচনা" করব?


231

প্রথমত, আমি জানি যে অ্যান্ড্রয়েডে কোনও অ্যাপ্লিকেশন সত্যই হত্যা করা / পুনরায় চালু করা উচিত নয়। আমার ব্যবহারের ক্ষেত্রে আমি কোনও নির্দিষ্ট ক্ষেত্রে আমার অ্যাপ্লিকেশনটি কারখানার পুনরায় সেট করতে চাই যেখানে কোনও সার্ভার ক্লায়েন্টকে নির্দিষ্ট তথ্য প্রেরণ করে।

ব্যবহারকারীর কেবলমাত্র অ্যাপ্লিকেশনের এক উদাহরণ দিয়ে সার্ভারে লগ ইন করা যেতে পারে (যেমন একাধিক ডিভাইস অনুমোদিত নয়)। যদি অন্য কোনও উদাহরণটি "লগ-ইন" ​​-লোক পায় তবে সেই ধারাবাহিকতা বজায় রাখতে ব্যবহারকারীর সমস্ত অন্যান্য দৃষ্টান্ত তাদের ডেটা (ফ্যাক্টরি-রিসেট) মুছতে হবে।

জোর করে লক পাওয়া সম্ভব, কারণ ব্যবহারকারীর অ্যাপটি মুছে ফেলা এবং এটি পুনরায় ইনস্টল করতে পারে যার ফলশ্রুতিতে অন্যরকম আইডি-আইডি আসে এবং ব্যবহারকারী আর লকটি মুক্ত করতে সক্ষম হয় না। অতএব জোর করে লক পাওয়া সম্ভব।

সেই জোর-সম্ভাবনার কারণে আমাদের সর্বদা একটি কংক্রিট উদাহরণ পরীক্ষা করা দরকার যে এটিতে লক রয়েছে। এটি সার্ভারের প্রতিটি অনুরোধে (প্রায়) সম্পন্ন হয়। সার্ভারটি একটি "ভুল-লক-আইডি" প্রেরণ করতে পারে। যদি এটি সনাক্ত হয়, ক্লায়েন্ট অ্যাপ্লিকেশন অবশ্যই সবকিছু মুছে ফেলবে।


এটাই ছিল ইউস-কেস।

আমার একটি Activityএ আছে যা লগইন Activityএল বা অ্যাপটির মূল শুরু করে startsActivity বি ভাগ করে নেওয়া মূল্যগুলির উপর নির্ভর করে শুরু করে। এল বা বি শুরু করার পরে এটি নিজেকে বন্ধ করে দেয় যাতে কেবলমাত্র এল বা বি চলছে। ব্যবহারকারী ইতিমধ্যে লগ ইন করা ক্ষেত্রে এখন বি চলছে।

বি সি সি শুরু startServiceকরে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ক্রিয়াকলাপগুলি বি এবং সি ব্যবহার করি তবে এখনও চলছে। আমি লগইনে পিছনের বোতামটি চাপলে 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 ()) ব্যবহার করেছি; ওভার সিস্টেম.এক্সিট ();
এফডিআইএম

29
৪.৩ এবং ৪.৪ ডিভাইসে (সমস্ত আমি পরীক্ষিত করেছি) এটি বর্তমান ক্রিয়াকলাপটিকে মেরে ফেলবে এবং তারপরে পুরানোটির শীর্ষে একটি নতুন চালু করবে বলে মনে হচ্ছে। আমি 2 ডিগ্রি গভীর (প্রধান -> প্রিফেস)। পিছনে চাপলে আমার পুরানো অ্যাপ্লিকেশন, এক স্ক্রিন ফিরে আসে।
এমগামেরজ

5
আমার ক্ষেত্রে, লেনদেনটি পিছনে ফিরে আসার কারণে System.exit (0) কাজ করে না। পরিবর্তে আমি ক্রিয়াকলাপ.ফিনিশ () ব্যবহার করেছি; এবং এটি ঠিক কাজ করে।
একত্রিত করুন 3

6
কুলিন, বলছি! আপনি গুরুতর হতে পারে না! এই উদাহরণটি বাস্তব জীবনের উদাহরণের চেয়ে দিকের মতো। আপনার এই স্নিপেটটি শুরু করার ক্রিয়াকলাপের নাম, অভিপ্রায় আইডি এবং আপনার যাহা কিছু হোক না কেন মেকানিক্স থেকে প্রস্থান করতে হবে। অন্ধভাবে এটি অনুলিপি পেস্ট করবেন না।
ওলেগ কোশকিন

19
পশ্চাদপটের কার্যক্রম নতুন সীমাবদ্ধতার কারণে অ্যান্ড্রয়েড প্রশ্ন সঙ্গে আর কাজ করে না developer.android.com/preview/privacy/...
মার্কো Righini

103

আপনি কেবল কল করতে পারেন:

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

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

যা প্রসেসফিনিক্স লাইব্রেরিতে ব্যবহৃত হয়


বিকল্প হিসাবে:

এখানে @ ওলেগ কোশকিন উত্তরের কিছুটা উন্নত সংস্করণ।

আপনি যদি বর্তমান প্রক্রিয়াটি হ্রাস সহ আপনার ক্রিয়াকলাপটি পুনরায় চালু করতে চান তবে কোড অনুসরণ করার চেষ্টা করুন। এটিকে হেল্পার ক্লাসে বা যেখানে আপনার এটি প্রয়োজন সেখানে রাখুন।

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 মিলিস হ্রাস করেছেন। যাইহোক, জ্যাক ওয়ার্টনের এই লাইব্রেরি প্রসেসফিনিক্স এটি আরও ভাল এবং দ্রুত করে তবে এটি কেবলমাত্র অ্যাপ্লিকেশনটিতে এই ফাংশনটির জন্য গ্রন্থাগার যুক্ত করার মতো নয়।
ব্লুওয়্যার

@ ব্লুওয়্যার আমি আমার উত্তর আপডেট করেছি এবং
প্রসেসফোনিক্সের

@ মিম্পেঞ্জ, এই লোক "ইলিয়া_গাজম্যান" আরও ভাল কাজ করেছে এবং এ জাতীয় লাইব্রেরি ব্যবহার না করেই করেছে।
ব্লুওয়্যার

3
@ ব্লুওয়্যার - ইলিয়ার সমাধান ব্যতীত প্রক্রিয়াটি আরম্ভ হবে না, সুতরাং স্থিতিশীল ডেটা বা লোড হওয়া এনডিকে লাইব্রেরিগুলি সঠিকভাবে পুনরায় পুনর্নির্মাণ করা হবে না।
টেড হপ

কিছু হুয়াওয়ে এবং স্যামসাং ডিভাইসগুলির এই AlarmManagerসলিউশনটি ব্যবহার করা হলে কোনও খারাপ আচরণ করা বা নিয়ন্ত্রণ করতে নিষেধ রয়েছে ?
ব্লুওয়্যার

69

জ্যাক ওয়ার্টন সম্প্রতি তাঁর প্রসেসফিনিক্স লাইব্রেরি প্রকাশ করেছেন , এটি এটি নির্ভরযোগ্য উপায়ে করে। আপনাকে মূলত কেবল কল করতে হবে:

ProcessPhoenix.triggerRebirth(context);

গ্রন্থাগারটি স্বয়ংক্রিয়ভাবে কলিং ক্রিয়াকলাপ শেষ করবে, অ্যাপ্লিকেশন প্রক্রিয়াটি মেরে ফেলবে এবং পরে ডিফল্ট অ্যাপ্লিকেশন ক্রিয়াকলাপটি পুনরায় চালু করবে।


এটি কাজ করে বলে মনে হচ্ছে, তবে আমি একটি ক্র্যাশ পেয়েছি (যা রিপোর্ট হয়ে যায়)। নিশ্চিত না যে এটি আদর্শ।
বিকে-

1
আমার এই লিব নিয়ে কোনও সমস্যা ছিল না, তবে গিথুব
জেকওয়ার্টন /

আরগ, আমি বার্তাটি যথেষ্ট কাছে দেখিনি বলে আমি আমার মন্তব্য প্রত্যাহার করি। আমি আমার ডিফল্ট লঞ্চ ক্রিয়াকলাপে একটি অভিযুক্ত ফিল্টারটি অনুপস্থিত। প্রয়োজনীয় নির্ভুল অভিপ্রায় ফিল্টারগুলি লক্ষ্য করার উপযুক্ত হতে পারে।
বিকে-

1
এটি এখন পর্যন্ত সেরা সমাধান।
yongsunCN

1
@ শম্ভু আপনাকে <category android:name="android.intent.category.DEFAULT" />অ্যাপ ম্যানিফেস্টে আপনার ডিফল্ট ক্রিয়াকলাপ <ইন্টেন্ট-ফিল্টার> এ ট্যাগ যুক্ত করতে হবে।
মুহাম্মদ রেফায়াত

57

আমি নতুন APIs ব্যবহারের জন্য Ilya_Gazman উত্তরটি কিছুটা সংশোধন করেছি (ইনপ্যান্টকম্প্যাট এপিআই 26 শুরু করা হয় না)। রানটাইম.জেটআরটাইম ()। প্রস্থান (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
@ ম্যাকভিন আপনি যেখানে সিদ্ধান্ত নেবেন ঠিক করেছেন। ভাষা পরিবর্তন হওয়ার পরে আমার কেসটি অ্যাপ্লিকেশন পুনরায় চালু হয়েছিল।
অ্যান্ড্রয়েড_দেব

@ টেডহপ প্রতিটি উত্তরে "ভালো নয়" হিসাবে মন্তব্য করছেন, আপনার কি কোনও সম্ভাব্য সমাধান আছে? ব্যঙ্গাত্মক হচ্ছে না, সত্যিই কোনও অ্যাপ্লিকেশন পুনরায় তৈরি করা উচিত কোনও চিহ্ন ছাড়াই রেখে; স্ট্যাটিকস ভেরিয়েবল থেকে শ্রেণীর দৃষ্টান্তগুলিতে।
ফরিদ

1
@ ফরিড - কলিং Runtime.getRuntime().exit(0)(বা System.exit(0)) জড়িত যে কোনও সমাধান সম্ভবত কার্যকর হবে। আমার কিছু "ভাল না" মন্তব্যগুলি উত্তরের জন্য রয়েছে (যেমন ইলিয়া গাজম্যানের একটি যা এর পরে এই জাতীয় কলটি সংযোজন করার জন্য সম্পাদনা করা হয়েছিল
টেড হপ্প

37

IntentCompat.makeRestartActivityTask

এটি করার নতুন উপায় হ'ল ইনটেন্টকম্প্যাট.মেকেরেস্টার্টএক্টিভিটি টাস্ক ব্যবহার করে

এমন একটি ইন্টেন্ট তৈরি করুন যা অ্যাপ্লিকেশনটির কাজটি তার বেস স্থিতিতে পুনরায় চালু করতে ব্যবহৃত হতে পারে। এটি মেকমেনঅ্যাক্টিভিটির (কম্পোনেন্টনাম) এর মতো, তবে পতাকাগুলিও ইন্টেন্ট করে। ফ্ল্যাশ_এ্যাকটিভিটি_নেউভ_এইএসটিআইভিটি_এফএলজি_এসিটিভিটি_সিএলআর_এসএএসকে।

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
ব্লুওয়্যার

4
দুর্ভাগ্যক্রমে, IntentCompat.makeRestartActivityTaskএখন অবহেলিত । আপনি যদি সোর্স কোড পরিদর্শন , এটা শুধু পতাকা যোগ হিসাবে সহজ হিসাবে Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK
পল ল্যামার্টসমা


28

সত্যিই একটি দুর্দান্ত কৌশল আছে। আমার সমস্যাটি হ'ল কিছু সত্যই পুরানো সি ++ জনি লাইব্রেরি রিসোর্স ফাঁস করে। এক পর্যায়ে, এটি কাজ করা বন্ধ করে দেয়। ব্যবহারকারী অ্যাপটি থেকে বেরিয়ে এসে আবার চালু করার চেষ্টা করেছিল - কোনও ফলাফল ছাড়াই, কারণ কোনও ক্রিয়াকলাপ শেষ করা প্রক্রিয়াটি সমাপ্তকরণ (বা হত্যা) সমান নয়। (যাইহোক, ব্যবহারকারী চলমান অ্যাপ্লিকেশনগুলির তালিকায় যেতে এবং সেখান থেকে এটি থামাতে পারে - এটি কাজ করবে, তবে ব্যবহারকারীরা কীভাবে অ্যাপ্লিকেশনগুলি সমাপ্ত করবেন তা জানেন না))

আপনি যদি এই বৈশিষ্ট্যের প্রভাব পর্যবেক্ষণ করতে চান তবে 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() কার্যকর হয় এবং তারপরে প্রক্রিয়াটি আবার তৈরি হয়। এবং এই ক্রিয়াকলাপটি AndroidManLive.xML এ উল্লেখ করতে ভুলবেন না ml

এই পদ্ধতির সুবিধা হ'ল কোনও বিলম্ব নেই।

ইউপিডি: এটি অ্যান্ড্রয়েড ২.x এ কাজ করেছে, তবে অ্যান্ড্রয়েড ৪-এ কিছু পরিবর্তন হয়েছে।


3
আমি ক্রিয়াকলাপ.স্টার্টএটিভিটি ব্যবহার করেছি (i); কে System.exit (0); প্রতিভা সমাধান
সর্বাধিক 4

5
এই সমাধানটি আমার জন্য অ্যাপটি বন্ধ করে দেয় তবে এটি পুনরায় আরম্ভ হয় না। কমপক্ষে Android 4.3 এ 4.
কিরিল রাখমান

1
স্যামসাং গ্যালাক্সিতে মেগা অ্যান্ড্রয়েডে 4.2.2 এটি পুনরায় আরম্ভের অসীম লুপের কারণ ঘটায়। সুতরাং অ্যাপ্লিকেশন আবার শুরু হবে না।
গুণহান

@Gunhan 1) যদি আপনি প্রতিস্থাপন সেখানে কি ঘটছে System.exit(0)দ্বারা android.os.Process.killProcess(android.os.Process.myPid());? 2) অসীম লুপটির সম্ভবত সম্ভবত কোনও অ্যাপ পুনরায় চালু করার সময় তারা সর্বাধিকতম কার্যকলাপ সরিয়ে দেয় না। নীতিগতভাবে, আপনি একটি স্ট্যাটিক বুলিয়ান ভেরিয়েবল যুক্ত করতে পারেন, পুনরায় চালু করার ক্রিয়াকলাপটি শুরু করার আগে এটি সত্য করে রাখুন এবং পুনরায় চালু করার পরে এটি মিথ্যা হবে। সুতরাং ক্রিয়াকলাপটি পুনঃসূচনাটি ইতিমধ্যে ঘটেছে কিনা তা জানতে পারে (এবং যদি এটি ঘটে থাকে তবে কেবল () শেষ করুন । OTOH, আপনার প্রতিবেদনের অর্থ হ'ল কৌশলটি সমস্ত ডিভাইসে অভিন্নভাবে কাজ করে না।
18446744073709551615

@ গুনহাম যদি আপনি একই ক্রিয়াকলাপটি শুরু করেন যা পুনরায় চালু করার কারণ হয়ে থাকে তবে এটি কোনও ডিভাইসে অসীম লুপ হবে।
লুকাস হানাসেক

23

আমার সমাধান প্রক্রিয়া / অ্যাপ্লিকেশন পুনরায় আরম্ভ করে না। এটি কেবলমাত্র অ্যাপ্লিকেশনটিকে বাড়ির ক্রিয়াকলাপটি "পুনঃসূচনা" করতে দেয় (এবং অন্যান্য সমস্ত ক্রিয়াকলাপ খারিজ করে)। এটি ব্যবহারকারীদের কাছে পুনঃসূচনা করার মতো দেখায় তবে প্রক্রিয়াটি একই is আমি মনে করি কিছু ক্ষেত্রে লোকেরা এই প্রভাব অর্জন করতে চায়, তাই আমি এটিকে এফওয়াইআইতে এখানে রেখেছি।

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

আমি খুঁজে পেয়েছি যে এটি এপিআই ২৯ এবং তারপরে কাজ করে - অ্যাপটি হত্যা এবং পুনঃসূচনা করার উদ্দেশ্যে যদি মনে হয় যে ব্যবহারকারী এটি চালু না করে চালু করেছিল when

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>

আমি মন্তব্যগুলি দেখেছি দাবি করে যে একটি বিভাগের খেলাপি প্রয়োজন, কিন্তু আমি এটি পাইনি। আমি নিশ্চিত করেছি যে আমার অ্যাপ্লিকেশনটিতে অ্যাপ্লিকেশন অবজেক্টটি পুনরায় তৈরি হয়েছে, তাই আমি বিশ্বাস করি যে প্রক্রিয়াটি সত্যই নিহত হয়েছে এবং পুনরায় চালু হয়েছে।

আমি যার জন্য এটি ব্যবহার করি তার একমাত্র উদ্দেশ্য হ'ল ব্যবহারকারী ফায়ারবেস ক্র্যাশলাইটিসের জন্য ক্র্যাশ প্রতিবেদন সক্ষম বা অক্ষম করার পরে অ্যাপ্লিকেশনটি পুনরায় চালু করা। তাদের ডক্স অনুসারে, এই পরিবর্তনটি কার্যকর করতে অ্যাপটিকে পুনরায় চালু করতে হবে (প্রক্রিয়াটি মেরে ফেলা এবং পুনরায় তৈরি করা))


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, বা জনি ক্লাসগুলি তাদের বর্তমান অবস্থায় থেকে যায় এবং পুনরায় পুনর্নির্মাণ হয় না।
টেড হপ

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

2

ব্যবহার করুন:

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

এটি এপিআই স্তরের 16 (4.1) থেকে শুরু করে কাজ করে, আমি বিশ্বাস করি।


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

এটির আপনার ডিবাগারটি সংযোগ বিচ্ছিন্ন করার দুর্ভাগ্যজনক ফলাফল রয়েছে।
ডাঃসাতান 1

-3

আপনি আপনার বর্তমান ক্রিয়াকলাপটি এভাবে পুনঃসূচনা করতে পারেন:

টুকরা :

activity?.recreate()

ক্রিয়াকলাপ:

recreate()

3
এটি ওপি যা করতে চায় তা মোটেই নয়।
টেড হপ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.