Android Service Analysis (life cycle, start-up mode, the front desk Service)

Service is one of four major components android, second in importance only Activity, Android document describes him as follows:

Service component represents a time-consuming operation without affecting users or functionality of other applications to use.

In android all the components are running in the main thread, use the service when it needs a time-consuming operation to open another thread. But the use of Service, more manageable time-consuming operation because the service has a different life cycle. For example, applications playing music, usually controlled by the Service.

Start Service

Service can be initiated in two ways: Context.startService () or Context.bindService ();

Context.startService () method and start activity similar to:


    Intent i = new Intent(ServiceActivity.this, ServiceA.class);
    startService(i);

After using this method to start Service, Service calls were onCreate () and onStartCommand () method.
Service is stopping method:


Intent i = new Intent(ServiceTestActivity.this, ServiceA.class);
stopService(i);

You can also call stopSelf Service's () method stops.

When the service will be called the destruction of his onDestory () method, where the operation to release the resource.

Note that multiple launch Service, onCreate () method will not be called multiple times, only the first time the calls start (or the destruction of the Service re-start), but onStartCommand () method will be called multiple times.

The second way: Context.bindService ()


Intent i = new Intent(ServiceTestActivity.this, ServiceA.class);
bindService(i,connection,BIND_AUTO_CREATE);

Unbind method:


Intent i = new Intent(ServiceTestActivity.this, ServiceA.class);
unbindService(connection);

Service started in this way, when the life cycle approach as follows:

bindService->onCreate->onBind->unbindService->onUnbind->onDestroy

If you do not call unbindService method, when the activity of this Service destruction can be destroyed, but the memory leak occurs, the error will be reported as follows:


08-30 00:12:06.060 1937-1937/example.ylh.com E/ActivityThread: Activity example.ylh.com.service_demo.ServiceTestActivity has leaked ServiceConnection example.ylh.com.service_demo.ServiceTestActivity$1@513a0eb that was originally bound here
······                                                              

Therefore, in order to prevent memory leaks, or honest unbind it.

bindService startup, need pass two parameters, the first is the intent, the second is ServiceConnection, this is what is it?

After the start we knew Service, Service forehead began to run, but how and Activity interact with it, this time on the need ServiceConnection, ServiceConnection is an interface:


private ServiceConnection connection = new ServiceConnection() {
       @Override
       public void onServiceConnected(ComponentName name, IBinder service) {
           Log.e(TAG,"onServiceConnected");
       }

       @Override
       public void onServiceDisconnected(ComponentName name) {
           Log.e(TAG, "onServiceDisconnected");
       }
   };

onServiceConnected method is called as soon after onBind Service, expressed binding activity and service success, associate.
onServiceDisconnected way to represent Service and activity associated with failure, not bound, generally not called.
onServiceConnected method takes two parameters, the second parameter is a IBinder, IBinder this method is the return value onBind Service, so we can onBind return value and onServiceConnected way for activity and Service associate, below is a typical case :

activity of xml:


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/btn1"
            android:text="start"/>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/btn2"
            android:text="stop"/>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/btn3"
            android:text="action"/>
    </LinearLayout>

</RelativeLayout>

activity Code:


package example.ylh.com.service_demo;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;

import example.ylh.com.R;

/**
 * Created by yanglihai on 2017/8/17.
 */

public class ServiceTestActivity extends Activity {

    public static final String TAG = ServiceTestActivity.class.getSimpleName();

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mService = ((ServiceA.MyBinder) service).getService();
            Log.e(TAG,"onServiceConnected");
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.e(TAG, "onServiceDisconnected");
        }
    };

    private ServiceA mService ;

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

        findViewById(R.id.btn1).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent i = new Intent(ServiceTestActivity.this, ServiceA.class);
                bindService(i,connection,BIND_AUTO_CREATE);
            }
        });

        findViewById(R.id.btn2).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent i = new Intent(ServiceTestActivity.this, ServiceA.class);
                unbindService(connection);
            }
        });

        findViewById(R.id.btn3).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mService.doSomething();
            }
        });
    }
}

service code:


package example.ylh.com.service_demo;

import android.app.Service;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;

/**
 * Created by yanglihai on 2017/8/17.
 */

public class ServiceA extends Service {

    static final String TAG = ServiceA.class.getSimpleName();

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

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        Log.e(TAG, "onStartCommand");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();

        Log.e(TAG, "onDestroy");
    }

    @Override
    public boolean bindService(Intent service, ServiceConnection conn, int flags) {

        Log.e(TAG, "bindService");
        return super.bindService(service, conn, flags);
    }

    @Override
    public void unbindService(ServiceConnection conn) {
        super.unbindService(conn);
        Log.e(TAG, "unBindService");
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.e(TAG, "onUnbind");
        return super.onUnbind(intent);
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.e(TAG, "onBind" );
        return mbinder;
    }


    public void doSomething(){
        Log.e(TAG, "doSomething");
    }

    private MyBinder mbinder = new MyBinder();

    public class MyBinder extends Binder{

        public ServiceA getService(){
            return ServiceA.this;
        }
    }

}

In onServiceConnected method, by a strong turn to get the binder, in the instance of Service to get through getService (), it can be manipulated you want.

Reception Service
when the Service is started, if we do not stop calling method, Service will be running in the background, but when insufficient system memory may kill our Service, in order to avoid being killed by the system, the Service can set the foreground service, done by calling Service.startForeground ().
First on the code:

package example.ylh.com.service_demo;

import android.app.Notification;
import android.app.Service;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;

import example.ylh.com.R;

/**
 * Created by yanglihai on 2017/8/17.
 */

public class ServiceA extends Service {

    static final String TAG = ServiceA.class.getSimpleName();

    @Override
    public void onCreate() {
        super.onCreate();
        Log.e(TAG, "oncreate");

        Notification.Builder builder = new Notification.Builder(this);
        builder.setSmallIcon(R.mipmap.btn_home_vedio);
        builder.setContentTitle("视频通知");
        builder.setContentText("someone send you a video");
        Notification notification = builder.build();
        startForeground(2,notification);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        Log.e(TAG, "onStartCommand");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();

        Log.e(TAG, "onDestroy");
    }

}

In onCreate, create a notice that tells the user there is a background operation running. The first parameter startForeground () is a type int id, id needs to be noted that this can not be 0, or can not create the front desk.
Service during this operation, there will be a notification bar notification until Service stopped or call StopForeground (true), a notification will be able to disappear.

Add that no matter what kind of start-up mode, Service need to be declared in the manifest file:


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="example.ylh.com" >

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme" >
        <activity android:name=".MainActivity" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service android:name=".service_demo.ServiceA" />

    </application>

</manifest>
Published 17 original articles · won praise 12 · views 10000 +

Guess you like

Origin blog.csdn.net/qq_24295537/article/details/77692618