# Android Background Execution Limits
## 참고
- https://blog.miyam.net/78
- http://thoughtnerds.com/2018/02/best-practise-jobintentservice-android-example/
- [잠자기 및 앱 대기보드 최적화](https://developer.android.com/training/monitoring-device-state/doze-standby?hl=ko)
- [Android O에서의 백그라운드 처리를 위한 JobIntentService](https://medium.com/til-kotlin-ko/android-o에서의-백그라운드-처리를-위한-jobintentservice-250af2f7783c)
---
## 이슈
- 앱 Doze, App Standby 모드 > 백그라운드 제한.
---
## 백그라운드 실행제한
**앱 백그라운드(유휴상태) 상태**에서의
- 백그라운드서비스(Service) 제한.
- 브로드캐스트(Broadcast) 제한.
### 1. 백그라운드서비스 제한
- Oreo(Androd 8)+
1. 앱이 백그라운드에 진입후, 몇분 뒤 동작 중인 백그라운드 서비스는 중지되며 onDestroy()가 호출됨.
2. 앱이 백그라운드의 상태에서 startService()의 호출시 IllegalStateException 발생됨.
- targetSDK ≥ 26 백그라운드 실행 제한
- target SDK가 Android O(API Level 26) 이상에서의 백그라운드 실행제한.
- 안드로이드 N 이하 버전 제한 안됨.
>인용구
### 2. 암시적 브로드캐스트 인텐트 제한
- 매니페스트의 암시적 브로드캐스트 등록불가.
- 매니페스트에 명시적 브로드캐스트 등록가능.
- 암시적브로드캐스트란? 특정 앱을 대상으로 하지 않는 브로드캐스트.
listItemList;
private String mMenuUpdateDate;
@Override
public IBinder onBind(Intent arg0) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Resources res = getResources();
NotificationCompat.Builder builder = new NotificationCompat.Builder(this,NOTI_CHANNEL_ID);
builder.setContentTitle("Title");
builder.setContentText("Text");
builder.setTicker("Ticker");
builder.setLargeIcon(BitmapFactory.decodeResource(res, R.mipmap.ic_launcher));
builder.setSmallIcon(R.drawable.push_icon);
builder.setColor(Color.parseColor("#376dc8"));
// builder.setContentIntent(pendingIntent);
builder.setAutoCancel(true);
builder.setWhen(System.currentTimeMillis());
Notification notification = builder.build();
NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
nm.notify((int)0, builder.build());
startForeground(1, notification); // <<<<<<<<<<<<<< point
nm.cancel(0); // 바로 노티제거
} else {
/*
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setContentTitle(getString(R.string.app_name))
.setContentText("식단갱신")
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setAutoCancel(true);
Notification notification = builder.build();
builder.setSmallIcon(R.drawable.widget_icon);
builder.setContentTitle(PushLibraryAppReceiver.NOTI_MODE_FOOD_REFRESH_NAME);
builder.setContentText(PushLibraryAppReceiver.NOTI_MODE_FOOD_REFRESH_NAME);
builder.setTicker(PushLibraryAppReceiver.NOTI_MODE_FOOD_REFRESH_NAME);
NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
nm.notify((int)0, builder.build());
*/
startForeground(0,null);
}
}
@Override
public void onDestroy() {
// 서비스가 종료될 때 실행
super.onDestroy();
stopForeground(true);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//Toast.makeText(getApplicationContext(), "reflash", Toast.LENGTH_SHORT).show();
L.d(TAG, "onStartCommand startId: " + startId);
mContext = this;
if (intent != null) {
if (intent.hasExtra(AppWidgetManager.EXTRA_APPWIDGET_ID))
mAppWidgetId = intent.getIntExtra(
AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID);
PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
// TODO ~~~~~~
//.
//.
//.
//.
//.
boolean isScreenOn;
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
isScreenOn = pm.isScreenOn();
} else {
isScreenOn = pm.isInteractive();
}
if (isScreenOn) {
}
}
return super.onStartCommand(intent, flags, startId);
}
}
```
### 2. 암시적 브로드캐스트 예외 - [바로가기](https://developer.android.com/guide/components/broadcast-exceptions)
1. 암시적 브로드캐스트에 제한없이 사용가능한 브로드 캐스트도 존재합니다.
### 3. 앱은 런타임에 Context.registerReceiver()를 사용하여 브로드캐스트(암시적 또는 명시적)에 수신기를 등록.
- 암시적브로드캐스트란? 특정 앱을 대상으로 하지 않는 브로드캐스트.
"ACTION_PACKAGE_REPLACED" 는 기기상의 일부 패키지가 교체된 사실을 알려주기 위해, 등록된 모든 리스너로 전송되므로 "암시적 브로드캐스트".--- ## Soulution - [바로가기](https://developer.android.com/about/versions/oreo/background#migration) ### 1. 포그라운드 서비스의 실행 - Context.startForegroundService(); 1. API 26에 추가된 Context.startForegroundService() 호출. 2. Service.startForeground()를 통해 Notification과 연결 (Notification 연결 안하면 서비스 중지됨). #### 가. Service 실행 ```java Intent serviceIntent = new Intent(this, MyService.class); serviceIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId); serviceIntent.setData(Uri.parse(serviceIntent.toUri(Intent.URI_INTENT_SCHEME))); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { startForegroundService(serviceIntent); } else { startService(serviceIntent); } ``` #### 나. Create Notification Channel ( Oreo+ ) ```java final static String NOTI_CHANNEL_ID = "NOTI_CHANNEL_ID"; final static String NOTI_CHANNEL_ID_NAME = "NOTI_CHANNEL_ID_NAME"; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationManager nmRefresh= (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); NotificationChannel ncRefresh = new NotificationChannel(NOTI_CHANNEL_ID, NOTI_CHANNEL_ID_NAME, NotificationManager.IMPORTANCE_NONE); ncRefresh.setDescription("Description); ncRefresh.enableLights(true); ncRefresh.setLightColor(Color.GREEN); ncRefresh.enableVibration(false); ncRefresh.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE); nmRefresh.createNotificationChannel(ncRefresh); } ``` #### MyService.java ```java public class MyService extends Service { private final String TAG = this.getClass().getSimpleName(); Context mContext; private int mAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID; public static ArrayList
"ACTION_MY_PACKAGE_REPLACED" 는 패키지가 교체된 앱으로만 전송되므로, "암시적 브로드캐스트가 아닙니다."
'mobile > android' 카테고리의 다른 글
Mobile Web App(Android&IOS) Store & Run (0) | 2019.06.10 |
---|---|
shouldOverrideUrlLoading(WebView view, String url) deprecated 에 따른 버전별 처리 (0) | 2019.06.10 |
anroid life cycle (0) | 2015.02.17 |
android icon 해상도 (0) | 2015.01.02 |
안드로이드 액티비티 생명주기(android life cycle) (1) | 2015.01.02 |
댓글