资讯专栏INFORMATION COLUMN

Android Service

darry / 3375人阅读

摘要:用户可以手动添加自启动应用,添加后的应用中如果回调返回值是或,当用户在小米手机上长按键结束后,接下来未来的某个时间内,当系统内存足够可用时,依然可以按照上述规定重启。

Android Service

Service通常总是称之为“后台服务”,其中“后台”一词是相对于前台而言的,具体是指其本身的运行并不依赖于用户可视的UI界面,因此,从实际业务需求上来理解,Service的适用场景应该具备以下条件:

并不依赖于用户可视的UI界面(当然,这一条其实也不是绝对的,如前台Service就是与Notification界面结合使用的)

具有较长时间的运行特性

基础知识

定义:Android中的计算型组件

作用:提供需要在后台长期运行的服务(如复杂计算、下载等等)

特点:长生命周期的、没有用户界面、在后台运行

定义Service

下面代码片段显示的是一个最基本的Started Service的自定义方式:

public class MyService extends Service {

    public static final String TAG = "MyService";

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

    @Override
    public void onCreate() {
        super.onCreate();
        Log.w(TAG, "in onCreate");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.w(TAG, "in onStartCommand");
        Log.w(TAG, "MyService:" + this);
        String name = intent.getStringExtra("name");
        Log.w(TAG, "name:" + name);
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.w(TAG, "in onDestroy");
    }
}

onBind(...)函数是Service基类中的唯一抽象方法,子类都必须重写实现,此函数的返回值是针对Bound Service类型的Service才有用的,在Started Service类型中,此函数直接返回 null 即可。
onCreate(...)、onStartCommand(...)和onDestroy()都是Started Service相应生命周期阶段的回调函数。

声明Service

一般而言,从Service的启动方式上,可以将Service分为Started Service和Bound Service。无论哪种具体的Service启动类型,都是通过继承Service基类自定义而来。在使用Service时,要想系统能够找到此自定义Service,无论哪种类型,都需要在AndroidManifest.xml中声明,语法格式如下:


    android:exported=["true" | "false"]           
    android:icon="drawable resource"
    android:isolatedProcess=["true" | "false"]
    android:label="string resource"
    android:name="string"
    android:permission="string"
    android:process="string" >
    . . .

android:exported——能否接收其他App的发出的信息,这个属性默认值有点意思,其默认值是由有无intent-filter决定的,如果有intent-filter,默认值为true,否则为false。(receiver/activity/service中的此属性默认值遵循此规则)同时,需要注意的是,这个值的设定是以application或者application user id为界的,而非进程为界(一个应用中可能含有多个进程)
android:name ——对应Service类名
android:permission ——是权限声明
android:process ——详情

Started Service

Started Service相对比较简单,通过context.startService(Intent serviceIntent)启动Service,context.stopService(Intent serviceIntent)停止此Service。当然,在Service内部,也可以通过stopSelf(...)方式停止其本身

以下是代码测试片段:

public class MainActivity extends Activity {

    public static final String TAG = "MainActivity";
    private Button startServiceBtn;
    private Button stopServideBtn;
    private Intent serviceIntent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        startServiceBtn = (Button) findViewById(R.id.start_service);
        stopServideBtn = (Button) findViewById(R.id.stop_service);
        
        startServiceBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                serviceIntent = new Intent(MainActivity.this, MyService.class);
                startService(serviceIntent);
            }
        });
        
        stopServideBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                stopService(serviceIntent);
            }
        });
        
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.w(TAG, "in onDestroy");
    }
}
调用流程

当Client调用startService(Intent serviceIntent)后,如果MyService是第一次启动,首先会执行 onCreate()回调,然后再执行onStartCommand(Intent intent, int flags, int startId),当Client再次调用startService(Intent serviceIntent),将只执行onStartCommand(Intent intent, int flags, int startId),因为此时Service已经创建了,无需执行onCreate()回调。无论多少次的startService,只需要一次stopService()即可将此Service终止,执行onDestroy()函数(其实很好理解,因为onDestroy()与onCreate()回调是相对的)

onStartCommand方法

onStartCommand(Intent intent, int flags, int startId)

其中参数flags默认情况下是0,对应的常量名为START_STICKY_COMPATIBILITY

startId是一个唯一的整型,用于表示此次Client执行startService(...)的请求请求标识,在多次startService(...)的情况下,呈现0,1,2....递增。

另外,此函数具有一个int型的返回值,具体的可选值及含义如下:

START_NOT_STICKY :当Service因为内存不足而被系统kill后,接下来未来的某个时间内,即使系统内存足够可用,系统也不会尝试重新创建此Service。除非程序中Client明确再次调用startService(...)启动此Service。

START_STICKY :当Service因为内存不足而被系统kill后,接下来未来的某个时间内,当系统内存足够可用的情况下,系统将会尝试重新创建此Service,一旦创建成功后将回调onStartCommand(...)方法,但其中的Intent将是null,pendingintent除外。

START_REDELIVER_INTENT :与START_STICKY唯一不同的是,回调onStartCommand(...)方法时,其中的Intent将是非空,将是最后一次调用startService(...)中的intent。

START_STICKY_COMPATIBILITY :此值一般不会使用,所以注意前面三种情形就好。

以上的描述中,”当Service因为内存不足而被系统kill后“一定要非常注意,因为此函数的返回值设定只是针对此种情况才有意义的,换言之,当认为的kill掉Service进程,此函数返回值无论怎么设定,接下来未来的某个时间内,即使系统内存足够可用,Service也不会重启。

小米手机针对此处做了变更:
另外,需要注意的是,小米手机针对此处做了一定的修改。在“自启动管理”中有一个自启动应用列表,默认情况下,只有少应用(如微信、QQ、YY、360等)默认是可以自启动的,其他应用默认都是禁止的。用户可以手动添加自启动应用,添加后的应用中如果Started Service onStartCommand(...)回调返回值是START_STICKY或START_REDELIVER_INTENT,当用户在小米手机上长按Home键结束App后,接下来未来的某个时间内,当系统内存足够可用时,Service依然可以按照上述规定重启。当然,如果用户在 设置 >> 应用 >> 强制kill掉App进程,此时Service是不会重启的。
注:以上实验结论基于小米2S亲测。

参考资料

官方教程

郭霖(Service教程)

Service生命周期图解

Android总结篇系列:Android Service

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/66412.html

相关文章

  • Service 使用详解

    摘要:只能执行单一操作,无法返回结果给调用方,常用于网络下载上传文件,播放音乐等。绑定模式此模式通过绑定组件等调用启动此服务随绑定组件的消亡而解除绑定。 showImg(https://segmentfault.com/img/remote/1460000019975019?w=157&h=54); 极力推荐文章:欢迎收藏Android 干货分享 showImg(https://segme...

    freewolf 评论0 收藏0
  • Broadcast 使用详解

    摘要:静态注册广播的方法动态注册广播在中动态注册广播,通常格式如下动态注册广播动态注册监听灭屏点亮屏幕的广播在广播中动态注册广播请注意一定要使用,防止为空,引起空指针异常。绑定模式此模式通过绑定组件等调用启动此服务随绑定组件的消亡而解除绑定。 showImg(https://segmentfault.com/img/remote/1460000019975019?w=157&h=54); 极...

    Y3G 评论0 收藏0

发表评论

0条评论

darry

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<