天天看点

service 的四种使用场景与方法

今天晚上把service的用法整理一下,service在Android中的地位仅次于activity,其重要性可见一斑。下面主要从四个部分分别讲解:

分别是startService,bindservice(两个基础用法。通过log查看生命周期)messenger和aidl(Android IPC机制主要也是通过service与binder来实现的)

编写activityInfo类来管理这四个测试的activity类,方便activity之间的跳转,简化代码

package com.example.servicetest;

public class ActivityInfo
{
    private String name;
    private Class clazz;

    public ActivityInfo(String name, Class clazz)
    {
        super();
        this.name = name;
        this.clazz = clazz;
    }

    public String getName()
    {
        return name;
    }

    public Class getClazz()
    {
        return clazz;
    }

    public void setName(String name)
    {
        this.name = name;
    }

    public void setClazz(Class clazz)
    {
        this.clazz = clazz;
    }

}
           

测试主类 MainActivity代码:

package com.example.servicetest;

import java.util.Arrays;
import java.util.List;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;

public class MainActivity extends Activity
{
    private ListView mListView;

    private final List<ActivityInfo> mData = Arrays.asList(new ActivityInfo(
            "StartService", ActivityStartService.class), new ActivityInfo(
            "bindService", ActivityBindService.class), new ActivityInfo(
            "Menssenger", ActivityMessenger.class), new ActivityInfo("aidl",
            ActivityAidl.class));

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //初始化view,个人的风格而已
        initView();
    }

    private void initView()
    {
        mListView = (ListView) findViewById(R.id.lv_activity_main);
        //为listview设置adapter
        mListView.setAdapter(new MyAdapter(this, mData));
        mListView.setOnItemClickListener(new OnItemClickListener()
        {

            @Override
            public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
                    long arg3)
            {
                Intent intent = new Intent();
                //通过前面设计的activityInfo得到要跳转的activity的class
                intent.setClass(MainActivity.this, mData.get(arg2).getClazz());
                startActivity(intent);
            }
        });
    }
}
           

listView的adapter实现很简单,继承自baseAdapter,使用viewholder去优化listview,想必大家都了解。

(1)通过startService(Intent intent)的方式开启服务

package com.example.servicetest;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class ActivityStartService extends Activity implements OnClickListener
{

    private Button mButtonStart, mButtonStop;

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

    private void initView()
    {
        mButtonStart = (Button) findViewById(R.id.btn_start_service);
        mButtonStop = (Button) findViewById(R.id.btn_stop_service);
        mButtonStart.setOnClickListener(this);
        mButtonStop.setOnClickListener(this);
    }

    @Override
    public void onClick(View arg0)
    {
        switch (arg0.getId())
        {
        case R.id.btn_start_service:
        //开启service
            startService(new Intent(ActivityStartService.this,
                    StartService.class));
            break;
            //停止service
        case R.id.btn_stop_service:
            stopService(new Intent(ActivityStartService.this,
                    StartService.class));
            break;
        default:
            break;
        }
    }
}
           

service的实现:

package com.example.servicetest;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

public class StartService extends Service
{
    private final String TAG = "StartService";

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

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

    @Override
    public int onStartCommand(Intent intent, int flags, int startId)
    {
        Log.e(TAG, "----onStartCommand----");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public IBinder onBind(Intent arg0)
    {
        Log.e(TAG, "----onBind----");
        return null;
    }

    @Override
    public void onRebind(Intent intent)
    {
        Log.e(TAG, "----onReBind----");
        super.onRebind(intent);
    }

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

}
           
service 的四种使用场景与方法

(2)bindService的启动过程,需要注意的是通过bindService启动service时,当service正常结束的时候,是不会调用onServiceDisconnected方法的,即使手动调用了unBindService()方法。

package com.example.servicetest;

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 android.view.View.OnClickListener;
import android.widget.Button;

public class ActivityBindService extends Activity implements OnClickListener
{
    private Button mButtonBind, mButtonUnBind;
    private final String TAG = "ActivityBindService";

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

    private void initView()
    {
        mButtonBind = (Button) findViewById(R.id.btn_start_service);
        mButtonUnBind = (Button) findViewById(R.id.btn_stop_service);
        mButtonBind.setOnClickListener(this);
        mButtonUnBind.setOnClickListener(this);
    }

    @Override
    public void onClick(View arg0)
    {
        switch (arg0.getId())
        {
        case R.id.btn_start_service:
            bindService(
                    new Intent(ActivityBindService.this, StartService.class),
                    mConnection, BIND_AUTO_CREATE);

            break;
        case R.id.btn_stop_service:
            unbindService(mConnection);
            break;

        default:
            break;
        }
    }

    private final ServiceConnection mConnection = new ServiceConnection()
    {

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

        @Override
        public void onServiceConnected(ComponentName arg0, IBinder arg1)
        {
            Log.e(TAG, "----onServiceConnected----");
        }
    };
}
           
service 的四种使用场景与方法

(3)messenger使用service进行IPC通信:

messenger主要是使用了Ibinder机制,其本质也是使用了aidl,但是他的好处是不用手工编写aidl文件,也不用理会aidl的生成过程。使用么三messege 和 Handler进行消息进行传递通信。因为handler是线程安全而且是一对一的通信,所以当Android IPC是一对一的时候,可以考虑使用messenger代替aidl去实现进程间通信

package com.example.servicetest;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.Handler.Callback;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class ActivityMessenger extends Activity implements OnClickListener
{
    private final String TAG = "ActivityMessenger";
    private Button mButton, mButton2;
    private Messenger iMessenger;
    private final Handler mHandler = new Handler(new Callback()
    {

        @Override
        public boolean handleMessage(Message arg0)
        {
            switch (arg0.what)
            {
            case RemoteService.MSG_FROM_CLIENT:
                String msg = arg0.getData().getString("rsp");
                Log.e(TAG, msg);
                break;

            default:
                break;
            }
            return false;
        }
    });

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

    private void initView()
    {
        mButton = (Button) findViewById(R.id.btn_start_service);
        mButton.setOnClickListener(this);
        mButton2 = (Button) findViewById(R.id.btn_stop_service);
        mButton2.setOnClickListener(this);
    }

    @Override
    public void onClick(View arg0)
    {
        switch (arg0.getId())
        {
        case R.id.btn_start_service:
            bindService(
                    new Intent(ActivityMessenger.this, RemoteService.class),
                    mConnection, BIND_AUTO_CREATE);
            break;
        case R.id.btn_stop_service:
            unbindService(mConnection);
            break;
        default:
            break;
        }
    }

    private final ServiceConnection mConnection = new ServiceConnection()
    {

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

        @Override
        public void onServiceConnected(ComponentName arg0, IBinder arg1)
        {
            Log.e(TAG, "----onServiceConnected----");
            //初始化messenger
            iMessenger = new Messenger(arg1);
            //设置message的类型
            Message message = Message.obtain(null,
                    RemoteService.MSG_FROM_CLIENT);
            Bundle bundle = new Bundle();
            bundle.putString("msg", "msg from client");
            message.setData(bundle);
            //这一句很重要,表明该消息的回复消息处理的handler为上面定义的mHandler。
            message.replyTo = new Messenger(mHandler);
            try
            {
                iMessenger.send(message);
            } catch (RemoteException e)
            {
                e.printStackTrace();
            }
        }
    };
}
           

下面看看RemoteService类:

package com.example.servicetest;

import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Handler.Callback;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.util.Log;

public class RemoteService extends Service
{

    public static final int MSG_FROM_CLIENT = ;
    private final String TAG = "RemoteService";
    private Messenger iMessenger;
    private final Handler mHandler = new Handler(new Callback()
    {

        @Override
        public boolean handleMessage(Message arg0)
        {
            switch (arg0.what)
            {
            case RemoteService.MSG_FROM_CLIENT:
            //获得服务进程传递过来的msg
                String msg = arg0.getData().getString("msg");
                Log.e(TAG, msg);
                /**
                *注意前面设置过msg的replyTo为客户端定义的mHandler
                */
                iMessenger = arg0.replyTo;
                Bundle bundle = new Bundle();
                bundle.putString("rsp", "rsp from server");
                Message message = Message.obtain(null,
                        RemoteService.MSG_FROM_CLIENT);
                message.setData(bundle);
                try
                {
                    iMessenger.send(message);
                } catch (RemoteException e)
                {
                    e.printStackTrace();
                }
                break;
            default:
                break;
            }
            return false;
        }
    });

    @Override
    public IBinder onBind(Intent arg0)
    {
        return new Messenger(mHandler).getBinder();
    }

}
           
service 的四种使用场景与方法

(4)最后就是aidl方式,aidl是处理Android进程间通信的,可以实现一对多的通信,下面通过一个相加求和的例子来讲解

下面是aidl文件,在两个app项目中,需要设置包名一模一样,会在gen包下生成对应的Java文件

package com.example.servicetest;
/**
*注意书写规范
*interface 没有 public private 的修饰
*方法也没有public private的修饰
*/
interface AIDLSum{
    double sum(double d1, double d2);
}
           
package com.example.servicetest;

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.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class ActivityAidl extends Activity implements OnClickListener
{

    private Button mButton;
    private final String TAG = "ActivityAidl";
    private AIDLSum mAidlService;

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

    private void initView()
    {
        mButton = (Button) findViewById(R.id.btn_start_service);
        mButton.setOnClickListener(this);
    }

    @Override
    public void onClick(View arg0)
    {
        switch (arg0.getId())
        {
        case R.id.btn_start_service:
            bindService(new Intent(ActivityAidl.this, AIDLService.class),
                    mConnection, BIND_AUTO_CREATE);
            break;

        default:
            break;
        }
    }

    private final ServiceConnection mConnection = new ServiceConnection()
    {

        @Override
        public void onServiceDisconnected(ComponentName arg0)
        {

        }

        @Override
        public void onServiceConnected(ComponentName arg0, IBinder arg1)
        {
            Log.e(TAG, "----onServiceConnected----");
            //asInterface函数可以在gen的aidl对应的java文件中查看
            mAidlService = AIDLSum.Stub.asInterface(arg1);
            double sum;
            try
            {
                sum = mAidlService.sum(, );
                Log.e(TAG, sum + "");
            } catch (RemoteException e)
            {
                e.printStackTrace();
            }
        }
    };

    @Override
    protected void onDestroy()
    {
        super.onDestroy();
        unbindService(mConnection);
    };
}
           

最后看看AIDLService.java文件:

package com.example.servicetest;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

public class AIDLService extends Service
{
    private final String TAG = "AIDLService";

    @Override
    public IBinder onBind(Intent arg0)
    {
        Log.e(TAG, "----onBind----");
        return stub;
    }

//这里是处理逻辑的核心部分,就是实现了aidl中的interface中的接口函数
    private final AIDLSum.Stub stub = new AIDLSum.Stub()
    {

        @Override
        public double sum(double d1, double d2) throws RemoteException
        {
            return d1 + d2;
        }
    };

}
           
service 的四种使用场景与方法

以上就是service的四种使用场景。希望有所帮助

————————————–向死而生———————————

梅花香自苦寒来