[android] 응용 프로그램을 쫓아 내고 있습니까?



14 Answers

나는이 스레드의 미래 독자를 위해 여기에 수정을 추가하고 싶습니다. 이 특별한 뉘앙스가 내 이해를 오랫동안 벗어 났으므로 여러분 중 누구도 똑같은 실수를하지 않도록하고 싶습니다.

스택에 둘 이상의 활동이있는 경우 System.exit() 이 응용 프로그램을 종료하지 않습니다. 실제로 일어나는 일은 프로세스가 강제 종료되고 스택에서 한 번 적은 활동으로 즉시 재시작 된다는 입니다. Force Close 대화 상자를 통해 앱이 종료되거나 DDMS에서 프로세스를 종료하려고 할 때도 마찬가지입니다. 이것은 내가 아는 바에 따라 완전히 서류 미비 된 사실입니다.

간단히 말해서, 애플리케이션을 종료하려면 스택의 모든 활동을 추적하고 finish() 할 때 모든 작업을 finish() 해야합니다 (아니요, 반복 할 방법이 없습니다). 액티비티 스택이므로 모든 것을 직접 관리해야합니다. 심지어 이것이 실제로 프로세스 또는 사용자가 가질 수있는 매달린 참조를 죽이지는 않습니다. 단순히 활동을 끝내기 만하면됩니다. 또한, Process.killProcess(Process.myPid()) 가 더 잘 작동하는지 확실하지 않습니다. 나는 그것을 시험하지 않았다.

반면에 스택에 액티비티를 남겨 두는 것이 좋다면, Activity.moveTaskToBack(true) 는 프로세스를 배경으로하고 홈 화면을 표시하기 만하면됩니다.

긴 대답은이 행동 뒤에있는 철학에 대한 설명을 포함합니다. 이 철학은 여러 가지 가정에서 태어났다.

  1. 우선 앱이 포 그라운드에있는 경우에만 발생합니다. 백그라운드에 있다면 프로세스가 정상적으로 종료됩니다. 그러나 포 그라운드에있는 경우 운영 체제는 사용자가 수행중인 작업을 계속 수행하려고한다고 가정합니다. (DDMS에서 프로세스를 종료하려는 경우 먼저 홈 단추를 누르고 죽여야합니다.)
  2. 또한 각 활동이 다른 모든 활동과 독립적이라고 가정합니다. 예를 들어 앱이 브라우저 활동을 시작한 경우 (예 : 완전히 분리되어 나와 작성되지 않은 경우)는 종종 사실입니다. 브라우저 활동은 매니페스트 특성에 따라 동일한 작업에서 생성되거나 생성되지 않을 수 있습니다.
  3. 귀하의 활동이 완전히 자립적이며 잠시 통고로 살해 / 복구 될 수 있다고 가정합니다. (오히려 onSaveInstanceState 동안 효율적으로 직렬화하기에는 너무 많은 캐시 된 데이터에 의존하는 많은 활동이 내 앱에 있기 때문에이 특정 가정을 싫어합니다. 그러나 가장 잘 작성된 Android 앱의 경우 사실이어야합니다. 왜냐하면 당신의 앱이 백그라운드에서 언제 죽게 될지 결코 알 수 없기 때문이다.
  4. 마지막 요소는 많은 가정이 아니라 오히려 OS의 한계입니다 . 앱을 명시 적으로 종료하는 것은 앱이 손상되는 것과 동일하며, Android가 메모리를 회수하기 위해 앱을 종료하는 것과 동일합니다. 앱이 종료되거나 추락했는지 여부를 안드로이드가 알 수 없기 때문에 사용자가 중단 한 부분을 반환하기를 원한다고 가정하므로 ActivityManager가 프로세스를 다시 시작합니다.

생각할 때 이것은 플랫폼에 적합합니다. 첫째, 이것은 백그라운드에서 프로세스가 종료되고 사용자가 다시 돌아 왔을 때 발생하는 상황입니다. 따라서 중단 된 위치에서 다시 시작해야합니다. 둘째, 앱이 충돌하고 두려운 강제 닫기 대화 상자를 표시 할 때 발생합니다.

내 사용자가 사진을 찍어 업로드 할 수 있기를 바랍니다. 내 활동에서 Camera Activity를 실행하고 이미지를 반환하도록 요청합니다. 카메라가 현재 작업의 상단에 푸시됩니다 (자체 작업에서 생성되는 것이 아니라). 카메라에 오류가 발생하여 충돌이 발생하면 전체 응용 프로그램이 손상 될 수 있습니까? 사용자 입장에서는 카메라 만 실패하고 이전 활동으로 되돌려 야합니다. 따라서 스택에서 카메라를 제외한 모든 동일한 활동으로 프로세스를 다시 시작하기 만하면됩니다. 당신의 활동 모자 한 방울에서 살해되고 복원 될 수 있도록 설계 되어야 하기 때문에 이것은 문제가되어서는 안됩니다. 불행히도, 모든 앱이 그런 식으로 디자인 될 수있는 것은 아니므로, Romain Guy 또는 다른 누구에게도 알려지지 않아도 많은 사람들이 문제가됩니다. 따라서 우리는 대안을 사용해야합니다.

그래서, 나의 마지막 조언 :

  • 그 과정을 죽이려고하지 마십시오. 모든 액티비티에 대해 finish() 를 호출하거나 moveTaskToBack(true) 호출 moveTaskToBack(true) .
  • 프로세스가 충돌하거나 죽게되면, 나처럼 현재 메모리에 있던 데이터가 필요하면 루트 작업으로 돌아 가야합니다. 이렇게하려면 Intent.FLAG_ACTIVITY_CLEAR_TOP 플래그가 포함 된 Intent와 함께 startActivity() 를 호출해야합니다.
  • Eclipse DDMS 관점에서 앱을 종료하려면 포 그라운드에 있지 않는 것이 좋으며, 그렇지 않으면 스스로 다시 시작됩니다. 먼저 홈 단추를 누른 다음 프로세스를 종료해야합니다.
Question

안드로이드를 배우려고 시도하면서 계속 전진 하면서 다음과 같은 내용을 읽었습니다 .

질문 : 메뉴 옵션을 죽이지 않으면 사용자가 응용 프로그램을 종료 할 수 있습니까? 그러한 옵션이없는 경우 사용자가 응용 프로그램을 어떻게 종료합니까?

답 : (Romain Guy) : 사용자가 자동으로 처리하지 않습니다. 이것이 활동 라이프 사이클 (특히 onPause / onStop / onDestroy)의 목적입니다. 당신이 무엇을 하든지, "quit"또는 "exit"application button을 넣지 마십시오. Android의 애플리케이션 모델에서는 쓸모가 없습니다. 이는 또한 핵심 응용 프로그램의 작동 방식과 상반됩니다.

Hehe, 내가 안드로이드 세계에 걸릴 모든 단계마다 나는 어떤 종류의 문제에 빠진다 = (

분명히 Android에서 애플리케이션을 종료 할 수는 없습니다 (하지만 안드로이드 시스템은 느낄 때마다 앱을 완전히 파괴 할 수 있습니다). 그게 뭐야? 나는 "정상적인 앱"으로 기능하는 앱을 작성하는 것이 불가능하다고 생각하기 시작했습니다. 사용자가 앱을 종료 할 때 그 앱을 종료 할 수 있다는 것입니다. 그것은 OS에 의존해야하는 것이 아닙니다.

내가 만들려고하는 응용 프로그램은 Android 마켓 용 응용 프로그램이 아닙니다. 그것은 일반 대중이 "폭넓게"사용할 수있는 응용 프로그램이 아니며 매우 좁은 비즈니스 분야에서 사용되는 비즈니스 응용 프로그램입니다.

Windows Mobile 및 .NET에 존재하는 많은 문제를 해결하기 때문에 Android 플랫폼을 실제로 개발할 것을 고대하고있었습니다. 그러나 지난 주에 나에게 다소 방해가되었습니다 ... 안드로이드를 버릴 필요는 없지만 지금은별로 좋아 보이지 않습니다. = (

신청서를 정말로 종료 할 수있는 방법이 있습니까?




테드, 당신이 성취하고자하는 것은 지금 당장 생각하고있는 방법이 아니라 아마도 끝낼 수 있습니다.

나는 당신이 활동과 서비스에 대해 읽어 보길 권한다. "앱"이라는 용어 사용을 중단하고 구성 요소 (예 : 활동, 서비스)를 시작하십시오. Android 플랫폼에 대해 더 많이 배워야한다고 생각합니다. 그것은 표준 PC 응용 프로그램에서 사고 방식의 변화입니다. 귀하의 게시물 중 아무도 "활동"이라는 단어가 없다는 사실 (사실, 귀하의 단어가 아닌)은 귀하가 좀 더 읽을 필요가 있음을 알려줍니다.




For closing an app at any point use FLAG_ACTIVITY_CLEAR_TOP flag in Intent and then system.exit();

Or there is similar way, but without system.exit() when you want to exit call this method:

public void exit() {
    startActivity(new Intent(this, HomeActivity.class).
    setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | IntentCompat.FLAG_ACTIVITY_CLEAR_TASK).putExtra(EXIT_FLAG, true));
}

In your HomeActivity.onCreate() add following code

protected void onCreate(Bundle savedInstanceState) {
    if (getIntent().getBooleanExtra(EXIT_FLAG, false)) {
        if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) == 0) {
            finish();
        }
    }
......................

This will work without breaking the Android life-cycle.




Hmmmm...

I think that you just don't see the Android app the right way. You can do something almost like what you want easily:

  • Do the app activities save/restore state like it is encouraged in the developer livecycle documentation.

  • If some login is needed at the restore stage (no login/session information available) then do it.

  • Eventually add a button/menu/timeout in which case you will do a finish() without saving the login and other session info, making implicitly the end of app session: so if the app is started/brought to front again it will start a new session.

That way you don't really care if the app is really removed from memory or not.

If you really want to remove it from memory (this is discouraged, and BTW for what purpose?) you can kill it conditionally at the end of onDestroy() with java.lang.System.exit(0) (or perhaps restartPackage(..) ?). Of course do it only in the case where you want to "really end the app", because the onDestroy() is part of the normal lifecycle of activities and not an app end at all.




You apparently have found the answer you want in the finish() command. This will not remove your app from memory, but Android will do so whenever it needs the resources, so it doesn't make any difference that you won't be doing that explicitly.

I would only add that in order to attain the full effect that an application exit would typically have, you would want to reset the app's state to whatever its state is normally at the time it is first run after a boot of the device, just prior to calling finish() on all of your activities. That way, if the user selects your app again, it will appear to have been run "fresh," without any state left over from the point prior to the simulated "exit."

If there are some special actions that should only occur on "exit," such as saving the user's work or whatever, you can also perform them prior to the re-initialization part of the above routine.

This approach allows you to accomplish your goal of having an "exit" command without violating Android's philosophy of leaving the management of OS resources, including the closing of apps, in the hands of the operating system.

Personally, I would not use this approach, because Android users expect an app to preserve its continuity when they revisit it, and so they are not used to the modality of "exiting" an app. I would instead support a "clear" function that a user can invoke to reset the app to some default initial state, without the necessity of "leaving" it in the process.

The one exception would be when the user has hit the back button a sufficient number of times to cause the app to close. In that situation, there is no expectation on the user's part that state will have been saved (and if there is unsaved state in the app, then you, as the developer, should have code handling the back button that detects that unsaved data, and prompts the user to save it to SharedPreferences or to a file, or to some other non-volatile medium).

Regarding system.exit(0):

If you do decide to use system.exit(0) to close your app with rude finality (eg, as a result of a final back button press), then I would warn you that although for me this "works," and in some cases has been the only way I've been able to close an app without any trace of it remaining, there is one minor glitch that occurs in Jelly Bean when you use this approach.

Specifically, if you use the Recent Apps list to open your app, and then use the back button to close the app (with that close implemented via system.exit(0)), the Recent Apps list will become visible again, as it will never have been closed. If you then tap on your app's entry in that list to run it a second time from the same, already-open, Recent Apps list, there will be no response.

I suspect that the cause of this is that the Recent Apps list is holding on to a reference to your app that has become non-functional due to your having closed the app using system.exit(0). A more civilized closing of your app using finish() might have informed the OS in a manner that would have allowed it to refresh its Recent Apps list, but system.exit(0) apparently does not do this.

This is not a huge problem in and of itself, as very few people will open an app from Recent Apps, then exit it, and then immediately open it again from the same open Recent Apps list. And if they tap the home button and then re-open the Recent Apps list, your app's entry will be there, and it will be fully functional. But I think that it shows that the use of system.exit(0) can interfere with proper communication between your app and the OS, and this suggests that there may be other, more serious, possibly subtle, consequences of using this approach.




There is a (relatively) simple design which will allow you to get around the "exit" conundrum. Make your app have a "base" state (activity) which is just a blank screen. On the first onCreate of the activity, you can launch another activity that your app's main functionality is in. The "exit" can then be accomplished by finish()ing this second activity and going back to the base of just a blank screen. The OS can keep this blank screen in memory for as long as it wants...

In essence, because you cannot exit out to OS, you simply transform into a self-created nothingness.




The Linux kernel has a feature called Out-of-memory killer (as mentioned above, the policies are configurable at the userspace level as well as the kernel is not an optimal one, but by no means unnecessary).

And it is heavily used by Android:

Some userspace apps are available to assist with these kill apps, for example:




It took me longer to read this Q&A than to actually implement a semi-proper Android Application Lifecycle.

It's a GPS app that polls for points and sends the current location to a webservice every few seconds using a thread... This could be polling every 5 minutes in Ted's case for an update, then onStop can simply start the update activity Ted was soo concerned about if one was found (asynchronous Ted, don't code like a Windows programmer or your programs will run like Windows programs ... eww, it's not that hard).

I did some initial code in onCreate to set up things for the activity lifetime, including checkUpdate.start(); :

...

@Override
public void onStart() {
    super.onStart();
    isRemote = true;
    checkUpdate.resume();

    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2000, 0, luh);
}

@Override
public void onPause() {
    isRemote = false;
    checkUpdate.suspend();
    locationManager.removeUpdates(luh);
    super.onStop();
}

This code may be completely wrong, but it works. This is one of my first Android applications.

Voilà, an application that doesn't consume CPU when it's in the background, yet is instantly ready to reopen because it is in RAM (although not holding RAM as is the Android lifecycle) ... an app is always ready, it's a phone, guys/gals. If an app was to use up all the RAM and couldn't be shut down by the OS then the thing might stop ringing =P That's why the OS needs to be able to close your app when it's in the background (if your application isn't a resource hog it won't be closed BTW), so let's just write better applications.




Almost 99% of the time there is no need for an Android application to take over its own life cycle. Most of the time it comes down to better planning or smarter design of the application. For example, rather build an internal service (not exported) to handle downloads, etc., or design actions and tasks around user workflow.

But that being said, where there is a will there is a way. Android provides - through the android.os.Process class, a much better API than Java to control the underlying process. And unlike Java it does not treat the developer like a moron by hiding it all behind a simple java.lang.System.exit() call.

So how do you ask your application to commit suicide in Android? Well, the trick is simple:

Create your own Android application class by inheriting from the standard android.app.Application class (remember to declare it in the AndroidManifest.xml file).

Override the onCreate() method, and store the process ID which started your application:

this.pid = android.os.Process.myPid(); // Save for later use.

Now to kill your application, provide a kill() method:

android.os.Process.sendSignal(pid, android.os.Process.SIGNAL_KILL);

Now whenever you need your app to commit suicide just type cast the application context, and call your kill method!

((MySuicidalApp) context.getApplicationContext()).kill()

Just remember that due to the process management policies in Android, specifically related to services, Android may just opt to restart your service (see You should not use task killers on Android ).




I think the point is that there is no need to quit the app unless you have buggy software. Android quits the app when the user is not using it and the device needs more memory. If you have an app that needs to run a service in the background, you will likely want a way to turn the service off.

For example, Google Listen continues to play podcast when the app is not visible. But there is always the pause button to turn the podcast off when the user is done with it. If I remember correctly, Listen, even puts a shortcut in the notification bar so you can always get to the pause button quickly. Another example is an app like a twitter app for instance which constantly polls a service on the internet. These types of apps should really allow the user to choose how often to poll the server, or whether even to poll in a background thread.

If you need to have code that runs on exit, you can override onPause(), onStop(), or onDestroy() as appropriate. http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle




응용 프로그램을 모 놀리 식 응용 프로그램으로 생각하지 마십시오. 그것은 사용자가 귀하의 "응용 프로그램"과 상호 작용할 수있는 UI 화면 세트이며 안드로이드 서비스를 통해 제공되는 "기능"입니다.

신비한 앱이하는 일이 무엇인지 알지 못하는 것은 정말로 중요하지 않습니다. 사용자가 "응용 프로그램을 종료 할 때까지 일부 모니터링 또는 상호 작용을 수행하고 로그인 된 상태로 유지되는 일부 보안이 안전한 회사 인트라넷에 있다고 가정 해 봅시다. IT 부서에서 명령을 내리기 때문에 사용자는 인트라넷에서 언제 또는 언제 인하는지 매우 숙지해야합니다. 따라서 사용자가 "종료"하는 것이 중요합니다.

이것은 간단합니다. 알림 표시 줄에 "나는 인트라넷에 있거나 실행 중입니다."라는 알림을 보내는 서비스를 만듭니다. 해당 서비스에서 응용 프로그램에 필요한 모든 기능을 수행하도록하십시오. 사용자가 "응용 프로그램"과 상호 작용할 수있는 UI 비트에 액세스 할 수 있도록 해당 서비스에 바인딩하는 활동을하십시오. Android 메뉴를 종료하려면 -> 서비스 종료를 알리는 종료 (또는 로그 아웃 또는 기타) 버튼을 클릭 한 다음 활동 자체를 닫습니다.

이것은 모든 의도와 목적에 정확히 당신이 원하는 말입니다. Android 방식으로 완료되었습니다. Google 토크 나 Google지도 내비게이션을 보면이 "이탈"의 예가 가능한 사고 방식입니다. 유일한 차이점은 사용자가 응용 프로그램을 다시 작동시키려는 경우에 대비하여 활동에서 단추를 뒤로 밀면 UNIX 프로세스가 대기 상태에 빠질 수 있습니다. 이것은 실제로 메모리에 최근에 액세스 한 파일을 캐시하는 현대적인 운영 체제와 다르지 않습니다. Windows 프로그램을 종료 한 후 필요한 리소스는 여전히 메모리에 남아 있으므로 더 이상 필요없는 다른 리소스로 대체되기를 기다리고 있습니다. Android도 마찬가지입니다.

나는 정말로 당신의 문제를 보지 못합니다.




뒤로 단추를 누르거나 Activity 에서 finish() 를 호출하여 종료 있습니다 . 명시 적으로 제거하려는 경우 MenuItem 에서 finish() 를 호출하기 만하면됩니다.

Romain은 그것을 끝낼 수 없다는 말은 아니며 단지 무의미한 것입니다. 사용자는 응용 프로그램 수명주기 작동 방식에 따라 자동 저장 및 저장하는 스마트 소프트웨어를 작성하도록 권장하므로 업무를 중단하거나 저장하는 데 신경을 쓸 필요가 없습니다. 무슨 일이 있어도 상태를 복원합니다.




The Android application life cycle is designed for mobile phone users, not computer users.

The app life-cycle is the brutally simplistic paradigm required to turn a Linux server into a consumer appliance.

Android is Java over Linux, a real cross-platform server OS. That is how it spread so quickly. The app life-cycle encapsulates the underlying reality of the OS.

To mobile users, apps are just installed or not installed. There is no concept of running or exiting. In fact, app processes are meant to run until the OS releases them for their held resources.

Since this is , anyone reading this is a computer user and must turn off 90% of their knowledge to understand the mobile app lifecycle.




I would consider reading "Android Wireless Application Development" published by Addison-Wesley. I am just finishing it up and it is VERY thorough.

It appears that you have some fundamental misunderstandings of the Android platform. I too was a little frustrated at first with the application life-cycle of Android apps, but after coming to a greater understanding, I have come to really enjoy this approach. This book will answer all of your questions and much more. It really is the best resource I have found for new Android developers.

Also, I think you need to let go of a line-for-line port of the existing app. In order to port your application to the Android platform, some of the application design is going to change. The application-lifecycle used is necessary as mobile devices have very limited resources relative to desktop systems and allows Android devices to run several applications in an orderly and resource-aware fashion. Do some more in depth study of the platform, and I think you will realize that what you are wanting to do is entirely feasible. Best of luck.

By the way, I am no way affiliated with Addison-Wesley or any person or organization associated with this book. After re-reading my post I feel that I came off a little fanboyish. I just really, really enjoyed it and found it extremely helpful. :)




If you have 10,20 .. multiple Activities running and you want to finish all them and exit from system.

Create a static array in application class or constants class.

Constants

public class Constants {

public static ArrayList<Activity> activities = new ArrayList<Activity>();

}

MainActivity 이 배열에 현재 활동 참조 추가

activity = MainActivity.this; Constants.activities.add(activity);

public class MainActivity extends Activity {

    private ImageView imageButton;
    private Activity activity;


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        activity = MainActivity.this;
        Constants.activities.add(activity);

        imageButton = (ImageView) findViewById(R.id.camera);
        imageButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                // existing app.
                if (Constants.activities != null) {
                    for (int i = 0; i < Constants.activities.size(); i++) {
                        Activity s = Constants.activities.get(i);
                        s.finish();
                    }
                }
                //super.finish();
                finish();
                android.os.Process.killProcess(android.os.Process.myPid());
                System.exit(1);
            }
        });
    }
}


Related



Tags

android android