Android Service浅析

420 阅读3分钟

1 简述

service是Android的四大组件之一,是每一位安卓开发者必须掌握的一个知识点。
它是一个应用组件,代表应用程序希望在不与用户交互的情况下执行更长时间运行的操作,或提供功能供其他应用程序使用。
服务可由其他应用组件启动(如Activity),服务一旦被启动将在后台一直运行,即使启动服务的组件(Activity)销毁也不受影响。 此外,组件可以绑定到服务,以与之进行交互,甚至是执行进程间通信 (IPC)。

2 使用

1、创建service
如同创建activity一样,继承Service类,重载钩子函数即可。

public class LocalService extends Service {
    private NotificationManager mNM;

    // Unique Identification Number for the Notification.
    // We use it on Notification start, and to cancel it.
    private int NOTIFICATION = R.string.local_service_started;

    /**
     * Class for clients to access.  Because we know this service always
     * runs in the same process as its clients, we don't need to deal with
     * IPC.
     */
    public class LocalBinder extends Binder {
        LocalService getService() {
            return LocalService.this;
        }
    }

    @Override
    public void onCreate() {
        mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);

        // Display a notification about us starting.  We put an icon in the status bar.
        showNotification();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("LocalService", "Received start id " + startId + ": " + intent);
        return START_NOT_STICKY;
    }

    @Override
    public void onDestroy() {
        // Cancel the persistent notification.
        mNM.cancel(NOTIFICATION);

        // Tell the user we stopped.
        Toast.makeText(this, R.string.local_service_stopped, Toast.LENGTH_SHORT).show();
    }

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

    // This is the object that receives interactions from clients.  See
    // RemoteService for a more complete example.
    private final IBinder mBinder = new LocalBinder();

    /**
     * Show a notification while this service is running.
     */
    private void showNotification() {
        // In this sample, we'll use the same text for the ticker and the expanded notification
        CharSequence text = getText(R.string.local_service_started);

        // The PendingIntent to launch our activity if the user selects this notification
        PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
                new Intent(this, LocalServiceActivities.Controller.class), 0);

        // Set the info for the views that show in the notification panel.
        Notification notification = new Notification.Builder(this)
                .setSmallIcon(R.drawable.stat_sample)  // the status icon
                .setTicker(text)  // the status text
                .setWhen(System.currentTimeMillis())  // the time stamp
                .setContentTitle(getText(R.string.local_service_label))  // the label of the entry
                .setContentText(text)  // the contents of the entry
                .setContentIntent(contentIntent)  // The intent to send when the entry is clicked
                .build();

        // Send the notification.
        mNM.notify(NOTIFICATION, notification);
    }
}

2、启动service
两种方式:

  • startService
  • bindService

两种方式创建service会有所区别,也可以放在一起使用,得到两种方式带来的效果

3 startService 与 bindService

  • context.startService()
  • context.bindService()
  1. 启动服务该服务在其他组件调用 startService() 时创建,然后无限期运行,且必须通过调用 stopSelf() 来自行停止运行。此外,其他组件也可通过调用 stopService() 来停止此服务。服务停止后,系统会将其销毁。
  2. 绑定服务该服务在其他组件(客户端)调用 bindService() 时创建。然后,客户端通过 IBinder 接口与服务进行通信。客户端可通过调用 unbindService() 关闭连接。多个客户端可以绑定到相同服务,而且当所有绑定全部取消后,系统即会销毁该服务。(服务不必自行停止运行。)

这两条路径并非完全独立。您可以绑定到已使用 startService() 启动的服务。例如,您可以使用 Intent(标识要播放的音乐)来调用 startService(),从而启动后台音乐服务。随后,当用户需稍加控制播放器或获取有关当前所播放歌曲的信息时,Activity 可通过调用 bindService() 绑定到服务。此类情况下,在所有客户端取消绑定之前,stopService() 或 stopSelf() 实际不会停止服务。

service_lifecycle.png

4 安全问题

使用service需要注意一些安全上的问题。
1、如果不希望其他应用程序连接到service,需要在AndroidMainfest 文件标签中配置 android:exported="false",其它应用不可以调用。
2、Service接收到到数据应该谨慎验证并处理,如空指针校验等,或用 try catch 捕获所有异常,以防止应用出现拒绝服务漏洞。