Android 앱을 프로그래밍 방식으로 "다시 시작"하는 방법은 무엇입니까?


231

첫째, 안드로이드에서 실제로 응용 프로그램을 죽이거나 다시 시작해서는 안된다는 것을 알고 있습니다. 유스 케이스에서 서버가 클라이언트에 특정 정보를 보내는 특정 경우 애플리케이션을 공장 초기화합니다.

사용자는 하나의 응용 프로그램 인스턴스가있는 서버에서만 로그인 할 수 있습니다 (즉, 여러 장치는 허용되지 않음). 다른 인스턴스가 해당 "로그인 된"잠금을 받으면 일관성을 유지하기 위해 해당 사용자의 다른 모든 인스턴스가 데이터를 삭제 (공장 재설정)해야합니다.

사용자가 앱을 삭제하고 다시 설치하여 다른 인스턴스 ID를 초래하고 더 이상 잠금을 해제 할 수 없기 때문에 강제로 잠금을 얻을 수 있습니다. 따라서 강제로 잠금을 얻을 수 있습니다.

그 힘 가능성 때문에 우리는 항상 잠금이있는 구체적인 인스턴스를 확인해야합니다. 서버에 대한 거의 모든 요청에 ​​대해 수행됩니다. 서버가 "잘못된 잠금 ID"를 보낼 수 있습니다. 이것이 감지되면 클라이언트 애플리케이션이 모든 것을 삭제해야합니다.


그것은 유스 케이스였습니다.

sharedPrefs 값에 따라 Activity로그인 ActivityL 을 시작 하는 A 또는 앱의 기본 ActivityB가 있습니다. L 또는 B를 시작한 후에는 L 또는 B 만 실행되도록 자체 종료됩니다. 따라서 사용자가 이미 로그인 한 경우 B가 현재 실행 중입니다.

B는 C를 시작한다. C startServiceIntentServiceD를 요구한다 .

(A)> B> C> D

D의 onHandleIntent 메소드에서 이벤트가 ResultReceiver R로 전송됩니다 .

R은 이제 사용자에게 애플리케이션을 공장 재설정 (데이터베이스, sharedPrefs 등 삭제) 할 수있는 대화 상자를 제공하여 해당 이벤트를 처리합니다.

공장 재설정 후 응용 프로그램을 다시 시작하고 (모든 활동을 닫으려면) A 만 다시 시작하면 로그인 ActivityL이 시작되고 자체 종료됩니다.

(A)> L

대화 상자의 onClick 방법은 다음과 같습니다.

@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가 여전히 실행 중이라는 것입니다. 로그인시 뒤로 버튼을 누르면 ActivityC가 표시되지만 홈 화면으로 돌아가고 싶습니다.

설정하지 않으면 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?

D는 또한에 의해 시작된 백그라운드 작업에서 호출 될 수 Context있기 때문에 Activities '를 사용할 수 없습니다 .ServiceIntentAlarmManager

어떻게 이것을 (A)> L이되는 액티비티 스택으로 해결할 수 있습니까?

답변:


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 () 이상;
FDIM

29
4.3 및 4.4 장치 (내가 테스트 한 모든 장치)에서 현재 활동을 중단 한 다음 이전 활동 위에 새로운 것을 시작하는 것처럼 보입니다. 나는 2 가지 활동 깊이입니다 (main-> prefs). 뒤로 누르면 한 화면 뒤로 이전 앱으로 이동합니다.
Mgamerz

5
필자의 경우 트랜잭션이 롤백되면서 System.exit (0)이 작동하지 않았습니다. 대신에 나는 activity.finish ()를 사용했다; 잘 작동합니다.
통합

6
@Qulin, 여러분! 당신은 진지 할 수 없습니다! 이 예제는 실제 예제보다 방향과 유사합니다. 시작 활동 이름, 의도 ID 및 종료 메커니즘을 사용하여이 스 니펫을 수정해야합니다. 맹목적으로 복사하여 붙여 넣지 마십시오.
Oleg Koshkin

19
이는 백그라운드 작업에 새로운 제한에 안드로이드 Q와 함께 더 이상 작동하지 않습니다 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);
}

ProcessPhoenix 라이브러리 에서 사용되는


대안으로 :

@Oleg Koshkin 답변의 약간 개선 된 버전이 있습니다.

현재 프로세스 종료를 포함하여 활동을 다시 시작하려면 다음 코드를 시도하십시오. HelperClass 또는 필요한 곳에 배치하십시오.

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

또한 jni 클래스와 모든 정적 인스턴스를 다시 초기화합니다.


1
이 솔루션은 훌륭하지만 100 밀리 초를 줄인 경우에도 애플리케이션을 다시 시작할 때까지 몇 초 동안 지연됩니다. 그러나 Jack Wharton 의이 ProcessPhoenix 라이브러리 는 더 빠르고 신속하게 수행하지만 앱 내 에서이 기능에만 라이브러리를 추가 할 가치는 없습니다.
blueware

@blueware 나는 내 대답을 업데이트 ProcessPhonix 내부에 사용되는 코드를 추가 한
mikepenz

@ mikepenz,이 사람 "Ilya_Gazman"은 그러한 라이브러리를 사용하지 않고 훨씬 더 잘했습니다.
blueware

3
@blueware-Ilya의 솔루션을 제외하고는 프로세스가 다시 시작되지 않으므로 정적 데이터 또는로드 된 NDK 라이브러리가 올바르게 다시 초기화되지 않습니다.
Ted Hopp

일부 Huawei 및 Samsung 장치에는 AlarmManager이 솔루션을 사용하는 경우 제한 사항이 있으며 잘못 작동합니다.
blueware

69

Jake Wharton은 최근 자신의 ProcessPhoenix 라이브러리를 공개했습니다 . 당신은 기본적으로 전화해야합니다 :

ProcessPhoenix.triggerRebirth(context);

라이브러리는 자동으로 호출 활동을 종료하고 응용 프로그램 프로세스를 종료 한 후 기본 응용 프로그램 활동을 다시 시작합니다.


이것은 작동하는 것처럼 보이지만 충돌이 발생합니다 (보고 됨). 이것이 이상적이지 않다.
BK-


아아, 나는 메시지를 충분히 가까이 보지 않아서 내 의견을 철회했다. 기본 실행 활동에 의도 필터가 없습니다. 필요한 정확한 의도 필터를 주목할 가치가 있습니다.
BK-

1
이것이 지금까지 가장 좋은 솔루션입니다.
yongsunCN

1
@Shambhu <category android:name="android.intent.category.DEFAULT" />앱 매니페스트의 기본 활동 <intent-filter>에 태그를 추가해야합니다 .
Muhammed Refaat 11

57

새로운 API를 사용하도록 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(). 하나 또는 다른 하나에 대해 "더 나은"것은 없습니다 (하나가 얼마나 많은 타이핑을하는지 또는 하나의 추가 메소드 호출 레이어에 대해 걱정하지 않는 한).
Ted Hopp

위의 메소드를 언제 어디서 호출합니까?
Makvin

1
@Makvin 당신은 어디로 전화할지 결정합니다. 언어 변경 후 제 사례는 앱을 다시 시작했습니다.
android_dev

@TedHopp는 모든 답변에 "좋지 않음"으로 댓글을 달았습니다. 가능한 해결책이 있습니까? 냉소적이지 않으면 서 흔적을 남기지 않고 응용 프로그램을 다시 만들어야합니다. 정적 변수에서 클래스 인스턴스까지.
Farid

1
@FARID-전화 Runtime.getRuntime().exit(0)(또는 System.exit(0)) 와 관련된 모든 솔루션이 작동합니다. 내 "좋지 않은"의견 중 일부는 답변을위한 것입니다 (예 : Ilya Gazman이 그와 같은 부름을 포함하도록 편집 된 의견)
Ted Hopp

37

IntentCompat.makeRestartActivityTask

이를 수행하는 새로운 방법은 IntentCompat.makeRestartActivityTask 를 사용하는 것입니다.

기본 상태에서 응용 프로그램 작업을 다시 시작하는 데 사용할 수있는 의도를 만듭니다. 이것은 makeMainActivity (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);

6
그러면 작업이 다시 시작되지만 프로세스 나 Application개체를 다시 시작하지는 않습니다 . 따라서 모든 static데이터, Application또는 jni 클래스를 작성하는 동안 초기화 된 데이터 는 현재 상태를 유지하고 다시 초기화되지 않습니다.
Ted Hopp

2
@TedHopp 아, 나는 그 부분을 그리워했다. System.exit (0)을 추가했습니다. 그러나 100 % 작동하는지 확실하지 않습니다. 나는 나중에 그것을 시험 할 것이다
Ilya Gazman

1
오픈 소스 라이브러리를 사용하지 않고 최상의 솔루션입니다. 이 답변을 제공해 주셔서 감사합니다. +1
blueware

4
불행히도, IntentCompat.makeRestartActivityTask이제는 더 이상 사용되지 않습니다 . 소스 코드검사하면 간단하게 플래그를 추가하는 것만 큼 간단합니다 Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK.
Paul Lammertsma

IntentCompat.makeRestartActivityTask 제거
luckyhandler

28

정말 좋은 트릭이 있습니다. 내 문제는 정말 오래된 C ++ jni 라이브러리가 리소스를 유출한다는 것입니다. 어느 시점에서, 그것은 작동을 멈췄습니다. 활동 종료는 프로세스 종료 (또는 종료)와 동일하지 않으므로 사용자가 앱을 종료했다가 다시 시작하려고했습니다. (그러면 사용자는 실행중인 응용 프로그램 목록으로 이동하여 그 위치에서 중지 할 수 있습니다-작동하지만 사용자는 응용 프로그램을 종료하는 방법을 모릅니다.)

이 기능의 효과를 관찰하려면 static활동에 변수를 추가하고 버튼 누름과 같이 각각 증가 시키십시오. 애플리케이션 활동을 종료 한 후 애플리케이션을 다시 호출하면이 정적 변수는 해당 값을 유지합니다. (응용 프로그램이 실제로 종료 된 경우 변수에 초기 값이 할당됩니다.)

(그리고 대신 버그 를 수정 하고 싶지 않은 이유에 대해 언급해야합니다 .이 라이브러리는 수십 년 전에 작성되었으며 그 이후로 리소스가 유출되었습니다. 경영진은 항상 효과가 있다고 생각합니다 . 비용 해결 방법 대신 수정 프로그램을 제공하는 . 나는 당신이 아이디어를 얻는다고 생각합니다.)

이제 jni 공유 (일명 동적, .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 : Android 2.x에서 작동했지만 Android 4에서는 변경되었습니다.


3
나는 activity.startActivity (i)를 사용했다; System.exit (0); 천재 솔루션
max4ever

5
이 솔루션은 나를 위해 응용 프로그램을 닫지 만 다시 시작되지는 않습니다. 최소한 안드로이드 4.3 이상.
Kirill Rakhman

1
삼성 갤럭시 메가 안드로이드 4.2.2에서는 무한 반복 재시작이 발생합니다. 따라서 앱이 다시 시작되지 않습니다.
Gunhan

@Gunhan 1) 대체 할 경우 발생하는 System.exit(0)android.os.Process.killProcess(android.os.Process.myPid());? 2) 무한 루프는 아마도 앱을 다시 시작할 때 최상위 활동을 제거하지 않음을 의미합니다. 원칙적으로 정적 부울 변수를 추가하고 재시작 활동을 호출하기 전에 true로 설정하면 재시작 후 false가됩니다. 따라서 활동은 다시 시작이 이미 발생했는지 여부를 알 수 있습니다 (이 경우에는 finish () ). OTOH, 귀하의 보고서는 트릭이 모든 장치에서 동일하게 작동하지 않는다는 것을 의미합니다.
18446744073709551615

@ 건함 다시 시작하는 동일한 활동을 시작하는 경우 모든 장치에서 무한 루프됩니다.
Lukas Hanacek

23

내 솔루션이 프로세스 / 응용 프로그램을 다시 시작하지 않습니다. 앱이 홈 활동을 "다시 시작"하고 다른 모든 활동을 해제 할 수 있습니다. 사용자가 다시 시작하는 것처럼 보이지만 프로세스는 동일합니다. 어떤 경우에는 사람들이이 효과를 달성하기를 원한다고 생각합니다.

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

15

좋아, 나는 내 앱을 리팩터링했고 A를 자동으로 끝내지 않을 것이다. 나는 이것을 항상 실행시키고 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
이렇게하면 응용 프로그램 이 다시 시작 되지 않고 클래스 만 다시 작성됩니다. 따라서 클래스 내의 정적 변수는 이전 실행의 값을 유지합니다.
Brian White

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

24
이렇게하면 응용 프로그램 이 다시 시작 되지 않고 클래스 만 다시 작성됩니다. 따라서 클래스 내의 정적 변수는 이전 실행의 값을 유지합니다.
Brian White

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

API 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 카테고리가 필요하다고 주장하는 의견을 보았지만 그 경우가 아닙니다. 내 앱의 Application 객체가 다시 만들어 졌음을 확인 했으므로 프로세스가 실제로 종료되었다가 다시 시작되었다고 생각합니다.

내가 이것을 사용하는 유일한 목적은 사용자가 Firebase Crashlytics에 대한 충돌보고를 활성화 또는 비활성화 한 후 앱을 다시 시작하는 것입니다. 문서에 따르면 변경 사항을 적용하려면 응용 프로그램을 다시 시작해야합니다 (프로세스 종료 및 다시 작성).


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

사용 다시 시작 또는 실행의 예 APPA 에서 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

JELLY BEAN 버전에서만 사용할 수 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
현재 작업의 모든 활동이 종료되지만 프로세스를 다시 시작하거나 응용 프로그램 개체를 다시 만들지 않습니다. 따라서 Application 작성 중 또는 jni 클래스에 의해 초기화 된 정적 데이터는 현재 상태로 유지되며 다시 초기화되지 않습니다.
Ted Hopp


3

다음은 PackageManager를 사용하여 일반적인 방식으로 앱을 다시 시작하는 예입니다.

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

그러면 작업이 다시 시작되지만 프로세스 나 Application개체를 다시 시작하지는 않습니다 . 따라서 정적 데이터,을 생성하는 동안 초기화 된 데이터 Application또는 jni 클래스는 현재 상태를 유지하고 다시 초기화되지 않습니다.
Ted Hopp 2016 년

3

이 시도:

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

1
여기에있는 다른 모든 대답과 마찬가지로 이미 동일한 것을 제안하면 응용 프로그램이 다시 시작되지 않고 클래스 만 다시 작성됩니다. 따라서 프로세스 내의 정적 데이터는 재설정되지 않습니다.
Ted Hopp

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

API 수준 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

프로세스 피닉스 라이브러리 . 다시 시작하려는 활동의 이름은 "A"입니다.

자바 맛

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

코 틀린 맛

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

이로 인해 디버거 연결이 끊어진 결과는 불행합니다.
DrSatan1

-3

다음과 같이 현재 활동을 다시 시작할 수 있습니다.

조각 :

activity?.recreate()

활동 :

recreate()

3
이것은 OP가 원하는 것이 아닙니다.
Ted Hopp
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.