Android Oreo JobIntentService继续在Android 7及以下版本的后台运行,并且经常在Android 8及以上版本中崩溃

Kal*_*i.G 6 android intentservice jobintentservice

我最近将我的所有服务都替换为前台服务和JobIntentService,因为在oreo及以上版本中有一些后台执行限制(https://developer.android.com/about/versions/oreo/background).根据文档,JobIntentService的行为类似于Android 7及以下版本的Intent Service,其作用类似于Android 8及以上版本的JobScheduler.我注意到Google提供的新JobIntentService存在问题.

Android 8及以上版本:

在Android 8及更高版本中连续发生崩溃.这里有一张提到同样问题的门票https://issuetracker.google.com/issues/63622293,我添加了一些极客建议的临时修复程序.

Android 7及以下版本: JobIntentService就像Intent Service一样,一旦完成工作就不会停止.

我在服务中实现了JobIntentService,只要用户执行某些操作就会触发该服务.

public class SampleJobIntentService extends FixedJobIntentService {

public static void postData(Context context, String data) {
    Intent intent = new Intent(context, SampleJobIntentService.class);
            intent.setAction(INITIAL_ACTION);
            intent.putExtra(SAMPLE_ID, data);
            SampleJobIntentService.enqueueWork(context,intent);
}

public static void enqueueWork(Context context, Intent work) {
    SampleJobIntentService.enqueueWork(context, SampleJobIntentService.class, JOB_ID, work);

 @Override
    protected void onHandleWork(@NonNull Intent intent) {
        if (intent != null) {
            SampleRequest sampleRequest = requests.get(intent.getAction());
            if (sampleRequest != null) {
                try {
                   // perform some networking operations
                } catch (Exception ex) {
                    Log.d("Error for intent ");
                }
                Log.i("send action ");
            } else
                Log.e("action not found for ");
        }
    }
    }
Run Code Online (Sandbox Code Playgroud)

为了避免JobIntentService崩溃,我从https://issuetracker.google.com/issues/63622293获取了一些参考资料

public abstract class FixedJobIntentService extends JobIntentService {

    @Override
    GenericWorkItem dequeueWork() {
        try {
            return new FixedGenericWorkItem(super.dequeueWork());
        } catch (SecurityException ignored) {
            doStopCurrentWork();
        }
        return null;
    }

    private class FixedGenericWorkItem implements GenericWorkItem {
        final GenericWorkItem mGenericWorkItem;

        FixedGenericWorkItem(GenericWorkItem genericWorkItem) {
            mGenericWorkItem = genericWorkItem;
        }

        @Override
        public Intent getIntent() {
            if (mGenericWorkItem != null) {
                return mGenericWorkItem.getIntent();
            }
            return null;
        }

        @Override
        public void complete() {
            try {
                if (mGenericWorkItem != null) {
                    mGenericWorkItem.complete();
                }
            } catch (IllegalArgumentException ignored) {
                doStopCurrentWork();
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

san*_*ane 11

嗯......,这是一个很大的理论...... !! 它无法将它全部放在这里.我会尽我所能,这将使你的概念清晰明白.


我已经失去了2年阅读谷歌文件的完整年份......哪些是use-less...随着no proper documentationno proper sample codes for its developers... !! 所以我在每一篇文章中都提到了这一点stack-overflow,因为它有助于节省其他人的时间.. !!


它看起来你是一个优秀的程序员; 只需要一些hints to your posted question:

提示-1:

你: - 我最近将我的所有服务都替换为前台服务和JobIntentService

前台服务:

如果你需要ALL THE TIME RUNNING PROCESS; WHICH WILL NEVER END... ONCE IT IS STARTED它的服务,它返回用于START_STICKY从它OnStartCommand.再次不建议使用,好像你想要不惜一切代价实现它...那么你将不得不使用一个通知,setOngoing(true)哪个最终用户无法刷掉你的通知,它将永远保留在那里...... .

使用前台服务:

接收器也有限制; 从上面Oreo开始,你不能通过在清单中声明它并仅通过制作一个接收器来使用所有接收器和意图动作......我建议只使用BootComplete权限并使用一个receiver接收boot_completed意图的单个并调用一个service低于O并调用一个现在,从前台服务实现所有的运行时接收器,并在Ondestroy方法中取消注册它.我从来没有找到实现运行时接收器的官方示例代码,最后我已经成功实施了几个月的艰苦工作......是的,因为谷歌不是一个聪明的工作

何时使用前台服务:

只有你想实现广播接收器....如果你不想实现任何广播接收器; 远离.......

提示-2:

你: - 我最近把我的所有服务都换成了前台服务 JobIntentService

**服务质量:**

只做一个非常微小的工作......然后退出...它必须被S退出topSelf()...再次,Services can cause data-loss如果被多次调用...同样的服务线程可以运行多次...再次如果你想要一项服务做很多工作......使用START_STICKY......但是不建议再次推荐,我已经建议,何时在提示1中使用它.

**Intentservice的质量如下:**

执行一个相对较长时间运行的任务,property of execution serially only如果你一次又一次地调用它intentService,那么所有的调用将被保存在一个queueone by one在完成后执行one by one.如上所述,这不是服务中的情况.它自己结束......没有必要由开发人员结束.. !!

**独特的品质:**

一旦他们是crashedandroid,可以阻止他们将来调用,而不会通知你,因为它崩溃的应用程序.需要与处理他们try-catch-exceptionavoid crash.再说......如果you are implementing threads within services那么try-catch-exception will not save your application from being crashing......

**那么地狱和如何实施,那么:**

使用FireBaseJobScedular: -

  1. 使用方便
  2. 使用简单的JobService
  3. 可以运行更长或更短的时间任务...... EVEN ALL THE TIME RUNNING TASK
  4. EVEN SUPPORTED BY NON STANDARD COMPANIES喜欢vivo,mi,oppo,one + 3,......这需要stock-android对它进行更改并给出FunTouchO,ColorOs,Oxygen等名称
  5. 只需要将电池设置更改为"不优化此应用"
  6. 是谷歌正式支持它并建议使用它
  7. 它创建GooglePlyService并在其中运行的实例,显然非标准公司也不会限制谷歌应用程序执行其任务.
  8. 适用于Oreo..,即使我已经测试过,Android P并且在Android 5.0版下工作作为AlarmManager任务.
  9. 我仍然建议使用minsdk above 16,target sdk 26好像万一你想上传你的应用程序,google play现在是强制性的,这个消息会听到你.和compile sdk 26.
  10. 只需绑定你JobService的清单并使用单行权限receive_boot_complete
  11. 只需安排它...它将在每个制造商的市场上的每个设备上启动......甚至在cold boothot boot
  12. 它最大限度地减少了很多代码和许多代码you can focus on actual tasks.
  13. 任务完成后,您可以return false指示任务已完成,它将结束JobService.

为什么我建议,因为我是CTO一个很好的UNKNOwn公司,并经历foreground service了许多类型的Android手机制造商造成的问题...这不是Apple and ios我们必须经历它.自18年以来一直是开发人员,我今天大部分都在编码...在所有开发项目中,我的开发策略仅由我来考虑.

纠正我......也是......因为你没有提到what your tasks并且 project与......有什么关系...你想要做什么 foreground service and intent-service......让我知道......,我很乐意帮助你.这是一个普遍的理论答案,而不是你想要的......但是为了给你实际答案,我需要你的项目范围.


Ank*_*kur 0

我想你只需要这么多代码。创建一个新的 MyJobIntentService 类并编写这么多代码并调用 postData() 来启动您的服务。

public class MyJobIntentService extends JobIntentService {

public static void postData(Context context, String data) {
    final Intent intent = new Intent(context, MyJobIntentService.class);
    intent.setAction(INITIAL_ACTION);
    intent.putExtra(SAMPLE_ID, data);
    enqueueWork(context, MyJobIntentService.class, 1000, intent);
}

@Override
public IBinder onBind(Intent intent) {
    return null;
}

@Override
public void onDestroy() {
    Ln.d("Cancelled service");
    super.onDestroy();
}

@Override
    protected void onHandleWork(@NonNull Intent intent) {
        if (intent != null) {
            final SampleRequest sampleRequest = requests.get(intent.getAction());
            if (sampleRequest != null) {
                try {
                   // perform some networking operations
                } catch (Exception ex) {
                    Log.d("Error for intent ");
                }
                Log.i("send action ");
            } else {                
               Log.e("action not found for ");
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

并确保在清单文件中添加您的服务

<service
            android:name="service.MyJobIntentService"
            android:exported="false"
            android:permission="android.permission.BIND_JOB_SERVICE" />
Run Code Online (Sandbox Code Playgroud)