Làm thế nào để tôi lập trình lại, khởi động lại một ứng dụng Android?


231

Đầu tiên, tôi biết rằng một người không nên thực sự giết / khởi động lại một ứng dụng trên Android. Trong trường hợp sử dụng của tôi, tôi muốn thiết lập lại ứng dụng của mình trong một trường hợp cụ thể trong đó máy chủ gửi thông tin cụ thể đến máy khách.

Người dùng chỉ có thể đăng nhập trên máy chủ với MỘT phiên bản của ứng dụng (tức là không cho phép nhiều thiết bị). Nếu một phiên bản khác nhận được rằng "đã đăng nhập" -lock thì tất cả các phiên bản khác của người dùng đó phải xóa dữ liệu của họ (khôi phục cài đặt gốc), để duy trì tính nhất quán.

Có thể buộc phải khóa, vì người dùng có thể xóa ứng dụng và cài đặt lại, điều này sẽ dẫn đến một id-id khác và người dùng sẽ không thể giải phóng khóa nữa. Do đó, có thể buộc phải có được khóa.

Do khả năng bắt buộc đó, chúng tôi cần phải luôn kiểm tra trong trường hợp cụ thể rằng nó có khóa. Điều đó được thực hiện trên (gần như) mỗi yêu cầu đến máy chủ. Máy chủ có thể gửi "id khóa sai". Nếu điều đó được phát hiện, ứng dụng khách phải xóa mọi thứ.


Đó là trường hợp sử dụng.

Tôi có một ActivityA bắt đầu Đăng nhập ActivityL hoặc ActivityB chính của ứng dụng tùy thuộc vào giá trị sharedPrefs. Sau khi bắt đầu L hoặc B, nó tự đóng lại để chỉ L hoặc B đang chạy. Vì vậy, trong trường hợp người dùng đã đăng nhập thì B đang chạy.

B bắt đầu C. C gọi startServicecho IntentServiceD. Điều đó dẫn đến ngăn xếp này:

(A)> B> C> D

Từ phương thức onHandleIntent của D, một sự kiện được gửi tới resultReceiver R.

Bây giờ R xử lý sự kiện đó bằng cách cung cấp cho người dùng một hộp thoại trong đó anh ta có thể chọn đặt lại nhà máy ứng dụng (xóa cơ sở dữ liệu, sharedPrefs, v.v.)

Sau khi khôi phục cài đặt gốc, tôi muốn khởi động lại ứng dụng (để đóng tất cả các hoạt động) và chỉ khởi động lại A sau đó khởi chạy ActivityL đăng nhập và tự hoàn tất:

(A)> L

Phương thức onClick của Dialog trông như thế này:

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

Và đó là MyApplớp học:

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

Vấn đề là nếu tôi sử dụng FLAG_ACTIVITY_NEW_TASKHoạt động B và C vẫn đang chạy. Nếu tôi nhấn nút quay lại khi đăng nhập, Activitytôi thấy C, nhưng tôi muốn quay lại màn hình chính.

Nếu tôi không đặt, FLAG_ACTIVITY_NEW_TASKtôi nhận được lỗi:

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?

Tôi không thể sử dụng Hoạt động ' Context, vì ServiceIntentD cũng có thể được gọi từ tác vụ nền được khởi động bởi AlarmManager.

Vậy làm thế nào tôi có thể giải quyết điều này để ngăn xếp hoạt động trở thành (A)> L?

Câu trả lời:


284

Bạn có thể sử dụng PendingIntentđể thiết lập khởi chạy hoạt động bắt đầu của mình trong tương lai và sau đó đóng ứng dụng của bạn

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
Điều này làm việc hoàn hảo cho tôi! Tôi chỉ sử dụng android.os.Process.killProcess (android.os.Process.myPid ()); trên System.exit ();
FDIM

29
Trên các thiết bị 4.3 và 4.4 (Tất cả tôi đã thử nghiệm), điều này dường như sẽ giết chết hoạt động hiện tại và sau đó khởi chạy một thiết bị mới trên đầu trang cũ. Tôi là 2 hoạt động sâu (chính -> prefs). Nhấn lại sẽ đưa tôi đến ứng dụng cũ, một màn hình trở lại.
Mgamerz

5
Trong trường hợp của tôi, System.exit (0) không hoạt động khi giao dịch được khôi phục. Thay vào đó tôi đã sử dụng Activity.finish (); và nó hoạt động tốt
thống nhất

6
@Qulin, các cậu! Bạn không thể nghiêm túc! Ví dụ này giống như hướng hơn là ví dụ thực tế. Bạn phải sửa đổi đoạn mã này với tên hoạt động bắt đầu, id mục đích và cơ chế thoát bất cứ điều gì bạn có. Đừng mù quáng sao chép nó.
Oleg Koshkin

19
Điều này không còn hoạt động nữa với Android Q do những hạn chế mới đối với nhà phát triển
nền.android.com/preview/privacy/iêu

103

Bạn chỉ có thể gọi:

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

Được sử dụng trong thư viện ProcessPhoenix


Như một sự thay thế:

Đây là một phiên bản cải tiến của câu trả lời @Oleg Koshkin.

Nếu bạn thực sự muốn khởi động lại hoạt động của mình, bao gồm cả việc hủy bỏ quy trình hiện tại, hãy thử làm theo mã. Đặt nó trong HelperClass hoặc nơi bạn cần.

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

Điều này cũng sẽ khởi tạo lại các lớp jni và tất cả các thể hiện tĩnh.


1
Giải pháp này rất hay, nhưng nó sẽ trì hoãn trong vài giây cho đến khi nó khởi động lại ứng dụng của bạn, ngay cả khi bạn giảm 100 Millis. Tuy nhiên, thư viện ProcessPhoenix của Jack Wharton này làm điều đó tốt hơn và nhanh hơn, nhưng thư viện không đáng để thêm chức năng này chỉ trong ứng dụng.
blucare

@bluware Tôi đã cập nhật câu trả lời của mình và thêm mã được sử dụng bên trong ProcessPhonix
mikepenz

@mikepenz, anh chàng "Ilya_Gazman" này đã làm tốt hơn nhiều và không sử dụng một thư viện như vậy.
blucare

3
@bluware - Ngoại trừ giải pháp của Ilya sẽ không khởi động lại quy trình, do đó, dữ liệu tĩnh hoặc thư viện NDK được tải sẽ không được khởi tạo lại một cách chính xác.
Ted Hopp

Một số thiết bị Huawei và Samsung có những hạn chế AlarmManagervà hành xử sai nếu sử dụng giải pháp này, Cách tiếp cận nào tốt hơn?
bluware

69

Jake Wharton gần đây đã xuất bản thư viện ProcessPhoenix của mình , thực hiện điều này một cách đáng tin cậy. Về cơ bản bạn chỉ phải gọi:

ProcessPhoenix.triggerRebirth(context);

Thư viện sẽ tự động kết thúc hoạt động gọi điện, hủy quá trình ứng dụng và khởi động lại hoạt động ứng dụng mặc định sau đó.


Điều này có vẻ hiệu quả, nhưng tôi gặp sự cố (được báo cáo). Không chắc đây là lý tưởng.
BK-

1
Tôi chưa bao giờ có bất kỳ vấn đề nào với lib, nhưng vui lòng báo cáo lỗi tại github.com/JakeWharton/ProcessPhoenix/issues
TBieniek

Argh, tôi rút lại nhận xét của mình khi tôi không nhìn vào tin nhắn đủ gần. Tôi đã thiếu một bộ lọc ý định về hoạt động khởi chạy mặc định của mình. Nó có thể đáng lưu ý các bộ lọc ý định chính xác cần thiết.
BK-

1
Đây là giải pháp tốt nhất.
yongsunCN

1
@Shambhu bạn phải thêm thẻ <category android:name="android.intent.category.DEFAULT" />vào hoạt động mặc định <bộ lọc ý định> trong bảng kê khai ứng dụng.
Muhammed Refaat

57

Tôi đã sửa đổi một chút câu trả lời của Ilya_Gazman để sử dụng các API mới (IntentCompat không dùng API bắt đầu 26). Runtime.getR.78 (). Exit (0) dường như tốt hơn 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
Trực tiếp từ các tài liệu : " Cuộc gọi System.exit(n) tương đương với cuộc gọi: Runtime.getRuntime().exit(n) ". Trong nội bộ, System.exit()chỉ cần quay lại và gọi Runtime.getRuntime().exit(). Không có gì "tốt hơn" về cái này hay cái kia (trừ khi người ta quan tâm đến việc gõ một cái bao nhiêu hoặc về một lớp gọi thêm phương thức).
Ted Hopp

Gọi phương thức ở đâu và khi nào?
Makvin

1
@Makvin bạn quyết định gọi nó ở đâu. Trường hợp của tôi là khởi động lại ứng dụng sau khi thay đổi ngôn ngữ.
android_dev

@TedHopp đã bình luận về mọi câu trả lời là "không tốt", bạn có giải pháp khả thi nào không? Không bị mỉa mai, thực sự cần phải tạo lại một ứng dụng mà không có bất kỳ dấu vết nào để lại; từ các biến thống kê đến các thể hiện của lớp.
Farid

1
@FARID - Bất kỳ giải pháp nào liên quan đến việc gọi Runtime.getRuntime().exit(0)(hoặc System.exit(0)) có thể sẽ hoạt động. Một số ý kiến ​​"không tốt" của tôi là dành cho câu trả lời (chẳng hạn như ý kiến ​​của Ilya Gazman đã được chỉnh sửa để kết hợp một cuộc gọi như vậy.
Ted Hopp

37

IntentCompat.makeRestartActivityTask

Cách thức mới để làm điều đó là bằng cách sử dụng IntentCompat.makeRestartActivityTask

Tạo một ý định có thể được sử dụng để khởi chạy lại nhiệm vụ của ứng dụng ở trạng thái cơ bản. Điều này giống như makeMainActivity (ElementName), nhưng cũng đặt các cờ Intent.FLAG_ACTIVITY_NEW_TASK và 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
Điều này khởi chạy lại nhiệm vụ, nhưng nó không khởi động lại quá trình, hoặc thậm chí Applicationđối tượng. Do đó, mọi staticdữ liệu, dữ liệu được khởi tạo trong quá trình tạo các lớp Applicationhoặc jni vẫn ở trạng thái hiện tại của chúng và không được khởi tạo lại.
Ted Hopp

2
@TedHopp ơi tôi đã bỏ lỡ phần đó. Tôi đã thêm System.exit (0); Nhưng tôi không chắc chắn 100% rằng nó sẽ hoạt động. Tôi sẽ kiểm tra nó sau
Ilya Gazman 14/03/2016

1
Giải pháp tốt nhất mà không cần sử dụng thư viện nguồn mở để làm điều đó. Hãy chung tay và cảm ơn vì đã cung cấp câu trả lời này, +1
blucare 22/8/2016

4
Thật không may, IntentCompat.makeRestartActivityTaskbây giờ không được chấp nhận . Nếu bạn kiểm tra mã nguồn , đơn giản chỉ cần thêm các cờ Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK.
Paul Lammertsma

IntentCompat.makeRestartActivityTask đã bị xóa
luckyhandler

28

Có một mẹo thực sự tốt đẹp. Vấn đề của tôi là một số thư viện jni C ++ thực sự cũ bị rò rỉ tài nguyên. Tại một số điểm, nó ngừng hoạt động. Người dùng đã cố thoát khỏi ứng dụng và khởi chạy lại - không có kết quả, vì việc hoàn thành một hoạt động không giống như hoàn thành (hoặc giết) quá trình. (Nhân tiện, người dùng có thể vào danh sách các ứng dụng đang chạy và dừng ứng dụng từ đó - việc này sẽ hoạt động, nhưng người dùng chỉ không biết cách chấm dứt ứng dụng.)

Nếu bạn muốn quan sát hiệu ứng của tính năng này, hãy thêm một staticbiến vào hoạt động của bạn và tăng từng biến, nhấn, nhấn nút. Nếu bạn thoát khỏi hoạt động ứng dụng và sau đó gọi lại ứng dụng, biến tĩnh này sẽ giữ giá trị của nó. (Nếu ứng dụng thực sự đã thoát, biến sẽ được gán giá trị ban đầu.)

(Và tôi phải bình luận về lý do tại sao tôi không muốn sửa chữa lỗi để thay thế. Các thư viện đã được viết cách đây nhiều thập kỷ và bị rò rỉ nguồn lực kể từ đó. Việc quản lý tin rằng nó luôn luôn làm việc . Các chi phí cung cấp một sửa chữa thay vì một workaround ... Tôi nghĩ rằng bạn có được ý tưởng.)

Bây giờ, làm cách nào tôi có thể đặt lại thư viện jni shared (aka động, .so) về trạng thái ban đầu? Tôi đã chọn khởi động lại ứng dụng như một quy trình mới.

Thủ thuật là System.exit () đóng hoạt động hiện tại và Android tạo lại ứng dụng với một hoạt động ít hơn.

Vì vậy, mã là:

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

Hoạt động gọi chỉ thực thi mã MagicAppRestart.doRestart(this);, hoạt động gọi onPause()được thực thi và sau đó quy trình được tạo lại. Và đừng quên đề cập đến hoạt động này trong AndroidManifest.xml

Ưu điểm của phương pháp này là không có độ trễ.

CẬP NHẬT: nó hoạt động trong Android 2.x, nhưng trong Android 4 đã có gì đó thay đổi.


3
tôi đã sử dụng Activity.startActivity (i); System.exit (0); giải pháp thiên tài
tối đa

5
Giải pháp này đóng ứng dụng cho tôi, nhưng nó không khởi động lại. Ít nhất là trên Android 4.3.
Kirill Rakhman

1
Trên samsung galaxy mega android 4.2.2 Nó gây ra vòng lặp khởi động vô hạn. Vì vậy, ứng dụng sẽ không bắt đầu lại.
Gunhan

@Gunhan 1) điều gì xảy ra nếu bạn thay thế System.exit(0)bằng android.os.Process.killProcess(android.os.Process.myPid());? 2) một vòng lặp vô hạn rất có thể có nghĩa là họ không xóa hoạt động cao nhất khi họ khởi động lại một ứng dụng. Về nguyên tắc, bạn có thể thêm một biến boolean tĩnh, đặt nó thành true trước khi gọi hoạt động khởi động lại và sau khi khởi động lại nó sẽ sai. Do đó, hoạt động có thể tìm hiểu xem việc khởi động lại đã xảy ra hay chưa (và nếu nó đã xảy ra, chỉ cần kết thúc () ). OTOH, báo cáo của bạn có nghĩa là thủ thuật không hoạt động giống hệt nhau trên tất cả các thiết bị.
18446744073709551615

@Gunham Nếu bạn đang bắt đầu cùng một hoạt động gây ra khởi động lại thì đó sẽ là vòng lặp vô hạn trên bất kỳ thiết bị nào.
Lukas Hanacek

23

Giải pháp của tôi không khởi động lại quá trình / ứng dụng. Nó chỉ cho phép ứng dụng "khởi động lại" hoạt động gia đình (và loại bỏ tất cả các hoạt động khác). Nó trông giống như một khởi động lại cho người dùng, nhưng quá trình là như nhau. Tôi nghĩ rằng trong một số trường hợp mọi người muốn đạt được hiệu ứng này, vì vậy tôi chỉ để nó ở đây FYI.

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

15

Ok, tôi đã cấu trúc lại ứng dụng của mình và tôi sẽ không tự động hoàn thành A. Tôi để nó chạy luôn và hoàn thành nó thông qua onActivityResultsự kiện. Theo cách này, tôi có thể sử dụng các cờ FLAG_ACTIVITY_CLEAR_TOP+ FLAG_ACTIVITY_NEW_TASKđể có được những gì tôi muốn:

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

và trong 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);
}

Dẫu sao cũng xin cảm ơn!


23
Điều này sẽ không khởi động lại ứng dụng, chỉ tạo lại các lớp. Do đó, bất kỳ biến tĩnh nào trong các lớp sẽ giữ lại các giá trị từ các lần chạy trước.
Brian White

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

24
Điều này sẽ không khởi động lại ứng dụng, chỉ tạo lại các lớp. Do đó, bất kỳ biến tĩnh nào trong các lớp sẽ giữ lại các giá trị từ các lần chạy trước.
Brian White

14

Mã duy nhất không kích hoạt "Ứng dụng của bạn đã đóng đột ngột" như sau. Đó cũng là mã không dùng nữa mà không yêu cầu thư viện bên ngoài. Nó cũng không yêu cầu hẹn giờ.

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

Tôi đã thấy rằng điều này hoạt động trên API 29 trở lên - với mục đích giết và khởi động lại ứng dụng như thể người dùng đã khởi chạy nó khi nó không chạy.

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

Điều đó đã được thực hiện khi hoạt động launcher trong ứng dụng có điều này:

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

Tôi đã thấy các bình luận cho rằng cần có một thể loại DEFAULT, nhưng tôi không thấy đó là trường hợp. Tôi đã xác nhận rằng đối tượng Ứng dụng trong ứng dụng của tôi được tạo lại, vì vậy tôi tin rằng quá trình thực sự đã bị giết và khởi động lại.

Mục đích duy nhất mà tôi sử dụng này là để khởi động lại ứng dụng sau khi người dùng đã bật hoặc tắt báo cáo sự cố cho Firebase Crashlytics. Theo tài liệu của họ, ứng dụng phải được khởi động lại (quá trình bị giết và được tạo lại) để thay đổi đó có hiệu lực.


7

Cách tốt nhất để khởi động lại hoàn toàn một ứng dụng là khởi chạy lại nó, không chỉ là chuyển sang một hoạt động với FLAG_ACTIVITY_CLEAR_TOPFLAG_ACTIVITY_NEW_TASK. Vì vậy, giải pháp của tôi là làm điều đó từ ứng dụng của bạn hoặc thậm chí từ một ứng dụng khác, điều kiện duy nhất là phải biết tên gói ứng dụng (ví dụ: ' 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);
}

Ví dụ về khởi động lại sử dụng hoặc khởi chạy appA từ appB :

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

Bạn có thể kiểm tra xem ứng dụng có đang chạy hay không:

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

Lưu ý : Tôi biết câu trả lời này hơi lạc đề, nhưng nó có thể thực sự hữu ích cho ai đó.


5

Cách tốt nhất để khởi động lại ứng dụng của tôi là sử dụng finishAffinity();
Vì, chỉ finishAffinity();có thể được sử dụng trên các phiên bản JELLY BEAN, vì vậy chúng tôi có thể sử dụng ActivityCompat.finishAffinity(YourCurrentActivity.this);cho các phiên bản thấp hơn.

Sau đó sử dụng Intentđể khởi chạy hoạt động đầu tiên, vì vậy mã sẽ trông như thế này:

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

Hy vọng nó giúp.


1
Điều này kết thúc tất cả các hoạt động trong tác vụ hiện tại, nhưng nó không khởi động lại quá trình, hoặc thậm chí tạo lại đối tượng Ứng dụng. Do đó, mọi dữ liệu tĩnh, dữ liệu được khởi tạo trong quá trình tạo Ứng dụng hoặc bởi các lớp jni vẫn ở trạng thái hiện tại của chúng và không được khởi tạo lại.
Ted Hopp


3

Dưới đây là một ví dụ để khởi động lại ứng dụng của bạn theo cách chung bằng cách sử dụng Trình quản lý gói:

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

Điều này khởi chạy lại nhiệm vụ, nhưng nó không khởi động lại quá trình, hoặc thậm chí Applicationđối tượng. Do đó, mọi dữ liệu tĩnh, dữ liệu được khởi tạo trong quá trình tạo các lớp Applicationhoặc jni vẫn ở trạng thái hiện tại của chúng và không được khởi tạo lại.
Ted Hopp

3

thử cái này:

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

1
Như mọi câu trả lời khác ở đây đã gợi ý điều tương tự, điều này sẽ không khởi động lại ứng dụng, chỉ tạo lại các lớp. Do đó, mọi dữ liệu tĩnh trong quy trình sẽ không được đặt lại.
Ted Hopp

2

Trực tiếp khởi động Màn hình ban đầu với FLAG_ACTIVITY_CLEAR_TASKFLAG_ACTIVITY_NEW_TASK.


2

Tôi đã phải thêm một Handler để trì hoãn việc thoát:

 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

Sử dụng:

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

Nó hoạt động bắt đầu từ API cấp 16 (4.1), tôi tin.


1

Bạn có thể sử dụng startInstrumentationphương pháp của Activity. Bạn cần thực hiện trống Instrumentationvà chỉ trong bảng kê khai. Sau đó, bạn có thể gọi phương thức này để khởi động lại ứng dụng của bạn. Như thế này:

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

Tôi nhận được tên lớp Thiết bị động nhưng bạn có thể mã hóa nó. Một số như thế này:

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

Gọi startInstrumentationthực hiện tải lại ứng dụng của bạn. Đọc mô tả của phương pháp này. Nhưng nó có thể không an toàn nếu hoạt động như ứng dụng kill.


1

Ứng dụng tôi đang làm việc phải cung cấp cho người dùng khả năng chọn những đoạn nào sẽ hiển thị (các đoạn được thay đổi động khi chạy). Giải pháp tốt nhất cho tôi là khởi động lại hoàn toàn ứng dụng.

Vì vậy, tôi đã thử rất nhiều giải pháp và không có giải pháp nào phù hợp với tôi, nhưng điều này:

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

Hy vọng rằng sẽ giúp đỡ người khác!


0

thử cái này:

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

Với thư viện Process Phoenix . Hoạt động bạn muốn khởi chạy lại được đặt tên là "A".

Hương vị Java

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

Hương vị Kotlin

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

Điều này có kết quả đáng tiếc làm cho trình gỡ lỗi của bạn bị ngắt kết nối.
DrSatan1

-3

Bạn có thể khởi động lại hoạt động hiện tại của mình như thế này:

Miếng :

activity?.recreate()

Hoạt động :

recreate()

3
Đây không phải là tất cả những gì OP muốn làm.
Ted Hopp
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.