1,显示启动
-
直接上代码一目了然,不解释了。
//显示启动
Intent intent = new Intent(this,ForegroundService.class);
startService(intent);
2, 隐式启动
-
需要设置一个Action,我们可以把Action的名字设置成Service的全路径名字,在这种情况下android:exported默认为true。
final Intent serviceIntent=new Intent();
serviceIntent.setAction("com.android.ForegroundService");
startService(serviceIntent);
3, 存在的意义
-
如果在同一个应用中,两者都可以用。在不同应用时,只能用隐式启动。
4, Android 5.0以上的隐式启动问题
-
Android 5.0之后google出于安全的角度禁止了隐式声明Intent来启动Service。如果使用隐式启动Service,会出没有指明Intent的错误,如下:
【1】主要原因
我们可以从源码中找到,这里看看Android 4.4的ContextImpl源码中的validateServiceIntent(Intent service),可知如果启动service的intent的component和package都为空并且版本大于KITKAT的时候只是报出一个警报,告诉开发者隐式声明intent去启动Service是不安全的.
而在android5.0之后呢?我们这里看的是android6.0的源码如下
源码可以看出如果启动service的intent的component和package都为空并且版本大于LOLLIPOP(5.0)的时候,直接抛出异常,该异常与之前隐式启动所报的异常时一致的。
【2】解决方式:
-
设置Action和packageName
final Intent serviceIntent=new Intent(); serviceIntent.setAction("com.android.ForegroundService");
serviceIntent.setPackage(getPackageName());//设置应用的包名
startService(serviceIntent);
-
将隐式启动转换为显示启动
public static Intent getExplicitIntent(Context context, Intent implicitIntent) {
// Retrieve all services that can match the given intent
PackageManager pm = context.getPackageManager();
List<ResolveInfo> resolveInfo = pm.queryIntentServices(implicitIntent, 0);
// Make sure only one match was found
if (resolveInfo == null || resolveInfo.size() != 1) {
return null;
}
// Get component info and create ComponentName
ResolveInfo serviceInfo = resolveInfo.get(0);
String packageName = serviceInfo.serviceInfo.packageName;
String className = serviceInfo.serviceInfo.name;
ComponentName component = new ComponentName(packageName, className);
// Create a new intent. Use the old one for extras and such reuse
Intent explicitIntent = new Intent(implicitIntent);
// Set the component to be explicit
explicitIntent.setComponent(component);
return explicitIntent;
}
-
调用方式如下:
Intent mIntent=new Intent();//辅助Intent
mIntent.setAction("com.android.ForegroundService");
final Intent serviceIntent=new Intent(getExplicitIntent(this,mIntent));
startService(serviceIntent);
关于更多Service内容:
https://blog.youkuaiyun.com/cricket_7/category_9580061.html
本文介绍了Android中Service的启动方式,包括显示启动和隐式启动。在同一个应用内,两者都可行,但跨应用时只能隐式启动。从Android 5.0开始,谷歌为了安全考虑限制了隐式启动Service,需要指定Intent。文章提供了解决方法,将隐式启动转换为显示启动,并给出了具体的调用示例。
3万+

被折叠的 条评论
为什么被折叠?



