앱이 닫히면 Android 서비스가 중지됨
다음과 같이 주요 Android 활동에서 서비스를 시작합니다.
final Context context = base.getApplicationContext();
final Intent intent = new Intent(context, MyService.class);
startService(intent);
최근 앱 목록에서 스 와이프하여 활동 페이지를 닫으면 서비스 실행이 중지되고 잠시 후 다시 시작됩니다. 앱 요구 사항으로 인해 알림과 함께 영구 서비스를 사용할 수 없습니다. 서비스가 다시 시작되거나 종료되지 않고 앱 종료시 계속 실행되도록하려면 어떻게해야합니까?
나는 같은 상황에 있는데, 지금까지 앱이 닫히면 서비스가 하나의 스레드에 있기 때문에 서비스가 닫히므로 서비스가 닫히지 않도록 다른 스레드에 있어야한다는 것을 배웠습니다. 여기에서 알람 관리자로 서비스를 유지하는 방법을 살펴보십시오. http://www.vogella.com/articles/AndroidServices/article.html 이렇게하면 서비스가 알림에 표시되지 않습니다.
마지막으로, 제가 수행 한 모든 조사 끝에 저는 장기 실행 서비스를위한 최선의 선택이라는 것을 깨달았습니다. startForeground()왜냐하면 그것이이를 위해 만들어졌고 시스템이 실제로 귀하의 서비스를 잘 처리하기 때문입니다.
이것은 당신을 도울 수 있습니다. 나는 착각 할 수 있지만 이것이 START_STICKY당신의 onStartCommand()방법 으로 돌아 오는 것과 관련이있는 것 같습니다 . START_NOT_STICKY대신 반환하여 서비스가 다시 호출되지 않도록 할 수 있습니다 .
Mainifest에서 이와 같은 서비스를 제공하십시오.
<service
android:name=".sys.service.youservice"
android:exported="true"
android:process=":ServiceProcess" />
그러면 서비스가 ServiceProcess라는 다른 프로세스에서 실행됩니다.
서비스가 절대 죽지 않게하려면 :
onStartCommand () 반환 START_STICKY
onDestroy ()-> startself
Deamon 서비스 생성
jin-> Native Deamon 프로세스 생성, github에서 일부 오픈 소스 프로젝트를 찾을 수 있습니다.
startForeground (), 알림없이 Foreground를 시작하는 방법이 있습니다.
앱을 닫을 때 서비스를 시작할 수없는 주요 문제, 안드로이드 OS ( 일부 OS )는 리소스 최적화를위한 서비스를 종료합니다. 서비스를 다시 시작할 수없는 경우 알람 관리자를 호출하여 다음과 같이 리시버를 시작합니다. 전체 코드입니다.이 코드는 서비스를 유지합니다.
매니페스트는
<service
android:name=".BackgroundService"
android:description="@string/app_name"
android:enabled="true"
android:label="Notification" />
<receiver android:name="AlarmReceiver">
<intent-filter>
<action android:name="REFRESH_THIS" />
</intent-filter>
</receiver>
IN Main Activty는 이런 식으로 알람 관리자를 시작합니다.
String alarm = Context.ALARM_SERVICE;
AlarmManager am = (AlarmManager) getSystemService(alarm);
Intent intent = new Intent("REFRESH_THIS");
PendingIntent pi = PendingIntent.getBroadcast(this, 123456789, intent, 0);
int type = AlarmManager.RTC_WAKEUP;
long interval = 1000 * 50;
am.setInexactRepeating(type, System.currentTimeMillis(), interval, pi);
이것은 수신자를 호출하고 수신자는
public class AlarmReceiver extends BroadcastReceiver {
Context context;
@Override
public void onReceive(Context context, Intent intent) {
this.context = context;
System.out.println("Alarma Reciver Called");
if (isMyServiceRunning(this.context, BackgroundService.class)) {
System.out.println("alredy running no need to start again");
} else {
Intent background = new Intent(context, BackgroundService.class);
context.startService(background);
}
}
public static boolean isMyServiceRunning(Context context, Class<?> serviceClass) {
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningServiceInfo> services = activityManager.getRunningServices(Integer.MAX_VALUE);
if (services != null) {
for (int i = 0; i < services.size(); i++) {
if ((serviceClass.getName()).equals(services.get(i).service.getClassName()) && services.get(i).pid != 0) {
return true;
}
}
}
return false;
}
}
그리고이 Alaram 리시버는 안드로이드 앱이 열리고 앱이 닫힐 때 한 번 호출됩니다.
public class BackgroundService extends Service {
private String LOG_TAG = null;
@Override
public void onCreate() {
super.onCreate();
LOG_TAG = "app_name";
Log.i(LOG_TAG, "service created");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(LOG_TAG, "In onStartCommand");
//ur actual code
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
// Wont be called as service is not bound
Log.i(LOG_TAG, "In onBind");
return null;
}
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
@Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
Log.i(LOG_TAG, "In onTaskRemoved");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i(LOG_TAG, "In onDestroyed");
}
}
서비스는 때때로 매우 복잡합니다.
활동 (또는 프로세스)에서 서비스를 시작할 때 서비스는 기본적으로 동일한 프로세스에 있습니다.
개발자 노트에서 인용
Service 클래스에 대한 대부분의 혼동은 실제로 그것이 아닌 것에 대한 것입니다.
A Service is not a separate process. The Service object itself does not imply it is running in its own process; unless otherwise specified, it runs in the same process as the application it is part of.
A Service is not a thread. It is not a means itself to do work off of the main thread (to avoid Application Not Responding errors).
So, what this means is, if the user swipes the app away from the recent tasks it will delete your process(this includes all your activities etc). Now, lets take three scenarios.
First where the service does not have a foreground notification.
In this case your process is killed along with your service.
Second where the service has a foreground notification
In this case the service is not killed and neither is the process
Third scenario If the service does not have a foreground notification, it can still keep running if the app is closed. We can do this by making the service run in a different process. (However, I've heard some people say that it may not work. left to you to try it out yourself)
you can create a service in a separate process by including the below attribute in your manifest.
android:process=":yourService"
or
android:process="yourService" process name must begin with lower case.
quoting from developer notes
If the name assigned to this attribute begins with a colon (':'), a new process, private to the application, is created when it's needed and the service runs in that process. If the process name begins with a lowercase character, the service will run in a global process of that name, provided that it has permission to do so. This allows components in different applications to share a process, reducing resource usage.
this is what I have gathered, if anyone is an expert, please do correct me if I'm wrong :)
From Android O, you cant use the services for the long running background operations due to this, https://developer.android.com/about/versions/oreo/background . Jobservice will be the better option with Jobscheduler implementation.
try this, it will keep the service running in the background.
BackServices.class
public class BackServices extends Service{
@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Let it continue running until it is stopped.
Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "Service Destroyed", Toast.LENGTH_LONG).show();
}
}
in your MainActivity onCreate drop this line of code
startService(new Intent(getBaseContext(), BackServices.class));
Now the service will stay running in background.
Using the same process for the service and the activity and START_STICKY or START_REDELIVER_INTENT in the service is the only way to be able to restart the service when the application restarts, which happens when the user closes the application for example, but also when the system decides to close it for optimisations reasons. You CAN NOT have a service that will run permanently without any interruption. This is by design, smartphones are not made to run continuous processes for long period of time. This is due to the fact that battery life is the highest priority. You need to design your service so it handles being stopped at any point.
You must add this code in your Service class so that it handles the case when your process is being killed
@Override
public void onTaskRemoved(Intent rootIntent) {
Intent restartServiceIntent = new Intent(getApplicationContext(), this.getClass());
restartServiceIntent.setPackage(getPackageName());
PendingIntent restartServicePendingIntent = PendingIntent.getService(getApplicationContext(), 1, restartServiceIntent, PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmService = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
alarmService.set(
AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime() + 1000,
restartServicePendingIntent);
super.onTaskRemoved(rootIntent);
}
Why not use an IntentService?
IntentService opens a new Thread apart from the main Thread and works there, that way closing the app wont effect it
Be advised that IntentService runs the onHandleIntent() and when its done the service closes, see if it fits your needs. http://developer.android.com/reference/android/app/IntentService.html
Best solution is to use the sync Adapter in android to start the service. Create a Sync Adapter and call start service their.. inside onPerformSync method. to create sync Account please refer this link https://developer.android.com/training/sync-adapters/index.html
Why SyncAdapter? Ans: Because earlier you used to start the service using your App context. so whenever your app process get killed (When u remove it from task manager or OS kill it because of lack of resources ) at that time your service will also be removed. SyncAdapter will not work in application thread.. so if u call inside it.. service will no longer be removed.. unless u write code to remove it.
<service android:name=".Service2"
android:process="@string/app_name"
android:exported="true"
android:isolatedProcess="true"
/>
Declare this in your manifest. Give a custom name to your process and make that process isolated and exported .
Running an intent service will be easier. Service in creating a thread in the application but it's still in the application.
Just override onDestroy method in your first visible activity like after splash you have home page and while redirecting from splash to home page you have already finish splash. so put on destroy in home page. and stop service in that method.
참고URL : https://stackoverflow.com/questions/16651009/android-service-stops-when-app-is-closed
'Program Club' 카테고리의 다른 글
| 하나의 PHP 포함 파일에서 다른 파일로 변수 전달 : 글로벌 vs. 아님 (0) | 2020.11.05 |
|---|---|
| iOS6 UDID-identifierForVendor가 identifierForAdvertising에 비해 어떤 이점이 있습니까? (0) | 2020.11.05 |
| SQL Server와 같은 절에서 조인을 사용하여 select 절에서 Postgresql 하위 쿼리를 수행하는 방법은 무엇입니까? (0) | 2020.11.04 |
| 여러 프로젝트 및 구성에 Visual Studio 프로젝트 속성을 효과적으로 사용 (0) | 2020.11.04 |
| matplotlib에서 줄 바꿈이있는 텍스트 상자? (0) | 2020.11.04 |