Service

A Service is an application component representing either an application’s desire to perform a longer-running operation while not interacting with the user or to supply functionality for other applications to use. Each service class must have a corresponding declaration in its package’s AndroidManifest.xml. Services can be started with Context.startService() and Context.bindService().

服务是一个应用程序组件,它表示应用程序希望在不与用户交互的情况下执行长时间运行的操作,或者提供其他应用程序使用的功能。每个服务类都必须在其包的 AndroidManifest.xml 中具有对应的 < service > 声明。可以使用 Context.startService ()和 Context.bindService ()启动服务。

Note that services, like other application objects, run in the main thread of their hosting process. This means that, if your service is going to do any CPU intensive (such as MP3 playback) or blocking (such as networking) operations, it should spawn its own thread in which to do that work. More information on this can be found in Processes and Threads. The JobIntentService class is available as a standard implementation of Service that has its own thread where it schedules its work to be done.

请注意,服务与其他应用程序对象一样,在其宿主进程的主线程中运行。这意味着,如果您的服务要执行任何 CPU 密集型(如 MP3播放)或阻塞(如网络)操作,它应该产生自己的线程来完成这项工作。有关这方面的更多信息可以在进程和线程中找到。JobIntentService 类作为服务的标准实现可用,它有自己的线程在其中安排要完成的工作。

服务本身实际上非常简单,提供两个主要特性:

  • A facility for the application to tell the system 用于应用程序告诉系统的设备about 关于 something it wants to be doing in the background (even when the user is not directly interacting with the application). This corresponds to calls to 它希望在后台执行某些操作(即使用户没有直接与应用程序交互)。这对应于调用Context.startService(), which ask the system to schedule work for the service, to be run until the service or someone else explicitly stop it. ,它要求系统为服务安排工作,直到服务或其他人显式停止它为止

  • A facility for an application to expose some of its functionality to other applications. This corresponds to calls to 应用程序向其他应用程序公开其某些功能的工具Context.bindService(), which allows a long-standing connection to be made to the service in order to interact with it. ,它允许与服务建立长期连接,以便与服务进行交互,当组件关闭它也会随之关闭

当一个服务组件实际创建时,出于以上任何一个原因,系统实际做的就是实例化该组件,并在主线程上调用其 onCreate ()和任何其他适当的回调。这取决于服务使用适当的行为来实现这些,例如创建一个在其中执行其工作的辅助线程。

There are two reasons that a service can be run by the system. If someone calls Context.startService() then the system will retrieve the service (creating it and calling its onCreate() method if needed) and then call its onStartCommand(Intent, int, int) method with the arguments supplied by the client. The service will at this point continue running until Context.stopService() or stopSelf() is called. Note that multiple calls to Context.startService() do not nest (though they do result in multiple corresponding calls to onStartCommand()), so no matter how many times it is started a service will be stopped once Context.stopService() or stopSelf() is called; however, services can use their stopSelf(int)` method to ensure the service is not stopped until started intents have been processed.

服务生命周期

系统可以运行服务有两个原因。如果有人调用 Context.startService () ,那么系统将检索该服务(创建它并根据需要调用其 onCreate ()方法) ,然后使用客户机提供的参数调用其 onStartCommand (Intent,int,int)方法。此时服务将继续运行,直到调用 Context.stopService ()或 stopSelf ()。注意,对 Context.startService ()的多个调用不会嵌套(尽管它们确实会导致对 onStartCommand ()的多个对应调用) ,因此无论启动多少次,一旦 Context.stopService ()或 stopSelf ()被调用,服务都会停止; 但是,服务可以使用它们的 stopSelf (int)方法来确保服务不会停止,直到启动的意图得到处理。

Clients can also use Context.bindService() to obtain a persistent connection to a service. This likewise creates the service if it is not already running (calling onCreate() while doing so), but does not call onStartCommand(). The client will receive the IBinder object that the service returns from its onBind(Intent) method, allowing the client to then make calls back to the service. The service will remain running as long as the connection is established (whether or not the client retains a reference on the service’s IBinder). Usually the IBinder returned is for a complex interface that has been written in aidl.

客户机还可以使用 Context.bindService ()获得到服务的持久连接。同样,如果服务尚未运行(在运行时调用 onCreate ()) ,但不调用 onStartCommand () ,则创建服务。客户机将接收服务从其 onBind (Intent)方法返回的 IBinder 对象,然后允许客户机对服务进行回调。只要连接建立起来,服务就会一直运行(不管客户机是否保留了服务的 IBinder 上的引用)。通常,返回的 IBinder 用于以 aidl 语言编写的复杂接口。

权限

Global access to a service can be enforced when it is declared in its manifest’s tag. By doing so, other applications will need to declare a corresponding element in their own manifest to be able to start, stop, or bind to the service.

在清单的< service >标记中声明服务时,可以强制对服务的全局访问。通过这样做,其他应用程序将需要在它们自己的清单中声明相应的 < uses-permission >元素,以便能够启动、停止或绑定到服务。


public class LocationService 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;

    // This is the object that receives interactions from clients.  See
    // RemoteService for a more complete example.
    // 这是接收来自客户端的交互的对象
    // 以获得更完整的示例。
    private final IBinder mBinder = new LocalBinder();

    //返回onBinder对象
    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }
   //创建需要完成的服务
    @Override
    public void onCreate() {
        mNM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        // Display a notification about us starting.  We put an icon in the status bar.
        showNotification();
    }


    /**
     * 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.
     */

    /*
    以便客户机访问。因为我们一直都知道这项服务
    *运行在与它的客户端相同的进程中,我们不需要处理
    * IPC。
    */
    public class LocalBinder extends Binder {
        LocationService getLocationService() {
            return LocationService.this;
        }
        void receive(String msg){
            Log.d("TAG", "receive: "+msg);
        }
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
//        onStartCommand绑定页面进行通信
        Log.i("LocalService", "Received start id " + startId + ": " + intent.getStringExtra(MainActivity.MAIN_ACTIVITY_SERVICE_INTENT));
        return START_NOT_STICKY;
    }

    /**
     * Show a notification while this service is running.
     */
    public 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, MainActivity.class), 0);

        // Set the info for the views that show in the notification panel.
        Notification notification = new Notification.Builder(this)
                .setSmallIcon(R.drawable.ic_android_black_24dp)  // 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);
    }
//  解除通知
    @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();
    }

}


/**
 * Example of binding and unbinding to the local service.
 * bind to, receiving an object through which it can communicate with the service.
 * <p>
 * Note that this is implemented as an inner class only keep the sample
 * all together; typically this code would appear in some separate class.
 */
public class MainActivity extends AppCompatActivity {
    public static final String MAIN_ACTIVITY_SERVICE_INTENT = "com.angle.serviceactivity.AppCompatActivity";

    // Don't attempt to unbind from the service unless the client has received some
    // information about the service's state.
    //除非客户端收到绑定,否则不要尝试解除绑定
    //服务状态的信息。
    private boolean mShouldUnbind;
    // To invoke the bound service, first make sure that this value
    // is not null.
    //要调用绑定服务,首先要确保此值
    //不为空。
    private LocationService mBoundService;
    private Button view;

    private Button views;
    private Intent intentService;

    private ServiceConnection mConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {
            // This is called when the connection with the service has been
            // established, giving us the service object we can use to
            // interact with the service.  Because we have bound to a explicit
            // service that we know is running in our own process, we can
            // cast its IBinder to a concrete class and directly access it.

            //当与服务的连接完成时调用
            //建立,为我们提供可以使用的服务对象
            //与服务交互。因为我们绑定到一个显式
            //我们知道在自己的进程中运行的服务,我们可以
            //将其IBinder转换为具体类并直接访问它。

//            绑定服务得到LocalBinder对象
            LocationService.LocalBinder service1 = (LocationService.LocalBinder) service;
//            通过接口回掉传值
            service1.receive("message for activity");
//            调用LocalBinder得到LocationService对象
            mBoundService = service1.getLocationService();

            // Tell the user about this for our demo.
            Toast.makeText(MainActivity.this, R.string.local_service_connected,
                    Toast.LENGTH_SHORT).show();
        }

        // 服务意外失去连接
        public void onServiceDisconnected(ComponentName className) {
            // This is called when the connection with the service has been
            // unexpectedly disconnected -- that is, its process crashed.
            // Because it is running in our same process, we should never
            // see this happen.
            //当与服务的连接完成时调用
            //意外断开连接——即进程崩溃。
            mBoundService = null;
            Toast.makeText(MainActivity.this, R.string.local_service_disconnected,
                    Toast.LENGTH_SHORT).show();
        }
    };

    void doBindService() {
        // Attempts to establish a connection with the service.  We use an
        // explicit class name because we want a specific service
        // implementation that we know will be running in our own process
        // (and thus won't be supporting component replacement by other
        // applications).

        //试图与服务建立连接。我们使用一个
        //显式类名,因为我们需要特定的服务
        //我们知道将在自己的进程中运行的实现
        //(因此不支持其他组件的替换
        //应用程序

//        创建Service连接
        intentService = new Intent(MainActivity.this, LocationService.class);
//         发送值将会在LocationService中onStartCommand得到
        intentService.putExtra(MAIN_ACTIVITY_SERVICE_INTENT, "message for activity");
        startService(intentService);
//        绑定Service
        if (bindService(intentService,
                mConnection, Context.BIND_AUTO_CREATE)) {
//            如果绑定确认解绑
            mShouldUnbind = true;
        } else {
            Log.e("MY_APP_TAG", "Error: The requested service doesn't " +
                    "exist, or this client isn't allowed access to it.");
        }
    }

    void doUnbindService() {
//        如果服务已经绑定
        if (mShouldUnbind) {
            // Release information about the service's state.
            //解绑服务
            unbindService(mConnection);
            mShouldUnbind = false;
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
//        当解Activity退出绑服务
        doUnbindService();
    }

    private void initView() {
        views = (Button) findViewById(R.id.views);
        views.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
//                创建服务绑定
                doBindService();
            }
        });
    }
}

个人心得
 1.服务分为2种

* startService
它要求系统为服务安排工作,直到服务或其他人显式停止它为止
* bindService
它允许与服务建立长期连接,以便与服务进行交互直到和它绑定的控件销毁而销毁
可以单个使用
* startService
* bindService

如果一起使用需要通过startService()先绑定在 bindService

2.绑定服务控件与服务交互
1.通过Binder创建方法使用接口回掉
2.通过startService(Intent intent)Intent传值在onStartCommand(Intent intent, int flags, int startId)接👋

GitHub Deome

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值