Service浅析

in Android with 0 comment

介绍

Service(服务)是一个没有用户界面的在后台运行执行耗时操作的应用组件。其他应用组件能够启动Service,并且当用户切换到另外的应用场景,Service将持续在后台运行。另外,一个组件能够绑定到一个service与之交互(IPC机制),例如,一个service可能会处理网络操作,播放音乐,操作文件I/O或者与内容提供者(content provider)交互,所有这些活动都是在后台进行。 Service有两种状态,“启动的”和“绑定”。

使用方法

看下关于Service两张比较经典的图 这里写图片描述

这里写图片描述

示例

AndroidManifest.xml

   <application
            android:label="@string/app_name"
            android:icon="@drawable/ic_launcher">

        <activity
                android:name=".MyActivity"
                android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <service android:name=".MyService"
                android:enabled="true"/>  <!--四大组件都要在AndroidManifest中申明一把 -->
    </application>

MyActivity.java

public class MyActivity extends Activity implements View.OnClickListener, ServiceConnection {
    public static String TAG = "MyActivity";

    Intent intent;

    /**
     * Called when the activity is first created.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        Log.e(TAG, "MyActivity OnCreate");
        intent = new Intent(MyActivity.this, MyService.class);

        findViewById(R.id.bt_startservice).setOnClickListener(this);
        findViewById(R.id.bt_stopservice).setOnClickListener(this);
        findViewById(R.id.bt_bindservice).setOnClickListener(this);
        findViewById(R.id.bt_unbindservice).setOnClickListener(this);
    }
    //OnClick事件监听
    public void onClick(View view) {
        Log.e(TAG,"OnClick");
        switch (view.getId()) {
            case R.id.bt_startservice:
                Log.e(TAG, "start Service");
                startService(intent);
                break;
            case R.id.bt_stopservice:
                stopService(intent);
                break;
            case R.id.bt_bindservice:
                bindService(intent, this, Context.BIND_AUTO_CREATE);
                break;
            case R.id.bt_unbindservice:
                unbindService(this);
                break;
        }
    }

    @Override //binderService成功后回调,带过来的IBinder可用于和Activity通信
    public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
        Log.e(TAG, "onServiceConnected");
    }

    @Override //在服务崩溃或被杀死导致的连接中断时被调用
    public void onServiceDisconnected(ComponentName componentName) {
        Log.e(TAG, "onServiceDisconnected");
    }
}

MyService.java

public class MyService extends Service {
    public static String TAG = "MyService";

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

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

        Log.e(TAG, "onStartCommand");
        
        //用来测试Service是否在后台有运行
        /*new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    Log.e(TAG, "Service is Running ...");
                }
            }
        }).start();*/
        return super.onStartCommand(intent, flags, startId);
    }

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

    @Override
    public IBinder onBind(Intent intent) {
        Log.e(TAG, "onBind");
        return new Binder();//new一个binder对象通过onServiceConnected回调,方便通信
    }

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

    @Override  //onRebind的调用时机和onUnbind的返回值有关系
    public void onRebind(Intent intent) {
        Log.e(TAG, "onRebind");
        super.onRebind(intent);
    }
}

结果

  1. 启动服务,停止服务 这里写图片描述

  2. 绑定服务,解绑服务 这里写图片描述

  3. 启动服务,绑定服务,解绑服务 这里写图片描述 注意:这里最后Service是没有onDestory的

  4. 启动服务,绑定服务,解绑服务,停止服务 这里写图片描述

5. Binder使用,这个很关键 MyService.java中修改

    public IBinder onBind(Intent intent) {
        Log.e(TAG, "onBind");
        return new MyBinder();
    }
   class MyBinder extends Binder {
        public void sayHello() {
            Log.e(TAG,"I am a binder, hi");
        }
    }

MyActivity.java中修改

    public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
        Log.e(TAG, "onServiceConnected");
        MyService.MyBinder binder = (MyService.MyBinder) iBinder;
        ((MyService.MyBinder) iBinder).sayHello();
    }

然后执行:绑定服务,解绑服务 这里写图片描述

通过这个Binder,再加上Callback,可以实现对Service内部状态的监听 先定义一个接口,然后创建get与set,在onBinder方法中定义一个线程不停的发送数据

public interface Callback() {
    public void onDateChanged(String data) {
    }
}

public void setCallback(Callback callback) {
    this.callback =  callback;
}

public Callback getCallback() {
    return callback;
}
    public IBinder onBind(Intent intent) {
        Log.e(TAG, "onBind");

        running = true;//running通过service的生命周期控制
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (running) {
                    try {
                        Thread.sleep(1000);
                        i++;
                        String str = "send: " + i ;
                        callback.onDateChanged(str);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    Log.e(TAG, "Service is Running ... ");
                }
            }
        }).start();
        return new MyBinder();
    }

然后在MyBinder类中定义一个getService方法

 public MyService getSetvice() {
     return MyService.this;
 }

然后在onServiceConnected中

public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
        Log.e(TAG, "onServiceConnected");
        MyService.MyBinder binder = (MyService.MyBinder) iBinder;
        MyService myservice = binder.getService();
        myservice.setCallback(new MyService.Callback() {
            @Override
            public void onDateChanged(String str) {//非UI线程无法直接更新UI,需要通过handler机制
                Message msg = new Message();
                msg.arg1 = 1;
                Bundle bundle = new Bundle();
                bundle.putString("data", str);
                msg.setData(bundle);
                handler.sendMessage(msg);
            }
        });
    }

通过这种方式就可以实现Service和Activity的通信工作,不难看出,Binder在其中起着非常重要的角色。 Android中进程间通信,从JAVA到C++基本上都是用Binder来实现的,上层使用的AIDL。

0评论