首页 文章

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

提问于
浏览
3

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

Android 8 & above:

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

Android 7 & below: 一旦工作完成,JobIntentService就像Intent Service一样不会停止 .

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

Code

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

为了避免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();
            }
        }
    }
}

3 回答

  • 0

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


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


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

    Hint-1 :

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

    foreground service :

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

    Use of the foreground service :

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

    When to use foreground service :

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

    Hint-2 :

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

    服务质量:

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

    ** Intentservice的质量如下:**

    执行相对较长时间运行的任务并且 property of execution serially only 如果您反复调用相同的 intentService ,则所有调用将保存在 queue 中,并在完成 one by one 后执行 one by one . 如上所述,这不是服务中的情况 . 它自己结束......没有必要由开发人员结束.. !!

    独特的品质:

    一旦他们 crashed 安卓可以阻止他们将来打电话而不通知你,因为它崩溃的应用程序 . 需要使用 try-catch-exception 来处理它们到 avoid crash . 再次......如果 you are implementing threads within services 那么 try-catch-exception will not save your application from being crashing ......

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

    使用 FireBaseJobScedular : -

    • 易于使用

    • 使用简单的JobService

    • 可以运行更长或更短的时间任务...... EVEN ALL THE TIME RUNNING TASK

    • EVEN SUPPORTED BY NON STANDARD COMPANIES 喜欢vivo,mi,oppo,one 3,...需要 stock-android 对其进行更改并给出FunTouchO,ColorOs,Oxygen等名称

    • 只需将电池设置更改为"Do not optimise this app"

    • 是谷歌正式支持它并建议使用它

    • It创建 GooglePlyService 的实例并在其中运行,显然也是非标准公司不会限制谷歌应用程序执行其任务 .

    • 适用于 Oreo ..,即使我已在 Android P 上测试过它,并且在Android 5.0版本下作为 AlarmManager 任务工作 .

    • 仍然我建议使用 minsdk above 16target sdk 26 ,好像万一你要将你的应用程序上传到 google play 它现在是强制性的,并且会听到你的消息 . 和 compile sdk 26 .

    • 在清单中绑定您的 JobService 并使用 receive_boot_complete 的单行权限

    • 只需安排它...它将在每个制造商的市场上的每台设备上启动......即使在 cold boothot boot

    • 它最大限度地减少了很多代码和 you can focus on actual tasks .

    • 任务完成后,您可以 return false 指示任务已完成,它将结束JobService .


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

    纠正我......也是......因为你还没有提到你的任务和项目与你有什么关系......以及你在前台服务和意向服务中想要做什么......让我知道..我很乐意帮助你 . 这是一个普遍的理论答案,而不是你想要的......但是为了给你实际答案,我需要你的项目范围 .

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

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

    <service
                android:name="service.MyJobIntentService"
                android:exported="false"
                android:permission="android.permission.BIND_JOB_SERVICE" />
    
  • 5

    JobIntentService which acts like Intent Service is not getting stopped once the work is done

    问题出在您的扩展类FixedJobIntentService dequeueWork方法中 .

    尝试将其更改为如下所示

    GenericWorkItem superValue = super.dequeueWork();
    if (superValue != null) {
        return new FixedGenericWorkItem(superValue);
    }
    return null;
    

    查看JobIntentSerivce代码,工作项处理器逻辑如下所示,即在队列中没有剩余工作项之前处理所有项目(即,为每个项目调用onHandleWork)

    while ((work = dequeueWork()) != null) {
            if (DEBUG) Log.d(TAG, "Processing next work: " + work);
            onHandleWork(work.getIntent());
            if (DEBUG) Log.d(TAG, "Completing work: " + work);
            work.complete();
        }
    

    实现中的问题是在处理完第一个工作项之后,super.dequeueWork()返回null,你没有处理它,只是发送一个新的FixedGenericWorkItem对象传递空值 . 您可能会发现在后续调用中将空值传递给onHandleWork .

    希望这有助于解决您的问题 .

相关问题