Android中Service的四种使用方式

Service是Android中的四大组件之一,用于在后台进行长时间作业,不提供用户界面。Service可以直接由其他的应用程序组件启动并在后台运行,也可以与其他组件绑定来实现进程间通信。本文介绍了创建Service的基本方法,并通过实例描述了Service的四种使用方式,包括Service的启动和绑定,以及IntentService和AIDL Service的使用。

0. 创建Service

  创建一个Service有两个步骤:实现Service子类,以及在manifest文件中声明该Service。

0.1. 实现Service子类

  与Activity类似,实现自己的Service子类时,需要重写一些回调方法,来管理Service的生命周期,如onStartCommand()onBind()onCreate()onDestroy()等。需要注意的是,onBind()是必须要重写的。举例来说,一个Service的简单实现如[代码0-1]所示,这个Service开启了一个线程来对count 进行累加和打印。

public class MyService extends Service {
private static final String TAG = "MyService";
private int count;
private boolean quit;
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "Service is created.");
count = 0;
quit = false;
new Thread() {
@Override
public void run() {
while (!quit) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
count++;
Log.i(TAG, "count = " + count);
}
}
}.start();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "Service is started.");
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
quit = true;
Log.i(TAG, "Service is destroyed.");
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
public class MyService extends Service { private static final String TAG = "MyService"; private int count; private boolean quit; @Override public void onCreate() { super.onCreate(); Log.i(TAG, "Service is created."); count = 0; quit = false; new Thread() { @Override public void run() { while (!quit) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } count++; Log.i(TAG, "count = " + count); } } }.start(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG, "Service is started."); return START_STICKY; } @Override public void onDestroy() { super.onDestroy(); quit = true; Log.i(TAG, "Service is destroyed."); } @Override public IBinder onBind(Intent intent) { return null; } }
public class MyService extends Service {

    private static final String TAG = "MyService";

    private int count;
    private boolean quit;

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i(TAG, "Service is created.");

        count = 0;
        quit = false;
        new Thread() {
            @Override
            public void run() {
                while (!quit) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    count++;
                    Log.i(TAG, "count = " + count);
                }
            }
        }.start();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(TAG, "Service is started.");
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        quit = true;
        Log.i(TAG, "Service is destroyed.");
    }

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

0.2. 在manifest文件中声明

  在manifest文件中声明Service的方法也与Activity类似,只需将<service…/> 插入到<application> 元素下面即可,如[代码0-2]所示。

<manifest ... >
...
<application ... >
<service android:name=".ExampleService" />
...
</application>
</manifest>
<manifest ... > ... <application ... > <service android:name=".ExampleService" /> ... </application> </manifest>
<manifest ... >
  ...
  <application ... >
      <service android:name=".ExampleService" />
      ...
  </application>
</manifest>

关于<service> 下的更多配置可以参考这里。Google的教程中指出,从安全角度考虑,在启动服务或绑定服务时尽量显式地指出所要使用的Service,而不要通过向Service加入Intent Filters来指明可以启动该Service的Intent。

1. 启动Service

  Service的启动可以通过调用Context中的startService()实现,相对应的,stopService()用于停止Service。

  新建一个Activity,命名为MyActivity;再新建一个如[代码0-1]所示的MyService,并按照[代码0-2]的形式在AndroidManifest.xml文件中声明MyService。在MyActivity中加入两个按钮btnStartService 和btnStopService ,分别用于启动和停止服务,如[代码1-1]所示。

public class MyActivity extends Activity {
private static final String TAG = "MyActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
final Intent serviceIntent = new Intent(this, MyService.class);
Button btnStartService = (Button)findViewById(R.id.btnStartService);
btnStartService.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
startService(serviceIntent);
}
});
Button btnStopService = (Button)findViewById(R.id.btnStopService);
btnStopService.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
stopService(serviceIntent);
}
});
}
}
public class MyActivity extends Activity { private static final String TAG = "MyActivity"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_my); final Intent serviceIntent = new Intent(this, MyService.class); Button btnStartService = (Button)findViewById(R.id.btnStartService); btnStartService.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { startService(serviceIntent); } }); Button btnStopService = (Button)findViewById(R.id.btnStopService); btnStopService.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { stopService(serviceIntent); } }); } }
public class MyActivity extends Activity {

    private static final String TAG = "MyActivity";

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

        final Intent serviceIntent = new Intent(this, MyService.class);
        Button btnStartService = (Button)findViewById(R.id.btnStartService);
        btnStartService.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                startService(serviceIntent);
            }
        });

        Button btnStopService = (Button)findViewById(R.id.btnStopService);
        btnStopService.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                stopService(serviceIntent);
            }
        });
    }
}

   运行MyActivity,点击按钮启动Service,然后再点击按钮停止Service,可以看到打印信息:
10-21 21:44:14.868 27063-27063/com.nex3z.servicetest I/MyService﹕ Service is created.
10-21 21:44:14.868 27063-27063/com.nex3z.servicetest I/MyService﹕ Service is started.
10-21 21:44:15.869 27063-27296/com.nex3z.servicetest I/MyService﹕ count = 1
10-21 21:44:16.870 27063-27296/com.nex3z.servicetest I/MyService﹕ count = 2
10-21 21:44:17.871 27063-27296/com.nex3z.servicetest I/MyService﹕ count = 3
10-21 21:44:18.802 27063-27063/com.nex3z.servicetest I/MyService﹕ Service is destroyed.
10-21 21:44:14.868 27063-27063/com.nex3z.servicetest I/MyService﹕ Service is created. 10-21 21:44:14.868 27063-27063/com.nex3z.servicetest I/MyService﹕ Service is started. 10-21 21:44:15.869 27063-27296/com.nex3z.servicetest I/MyService﹕ count = 1 10-21 21:44:16.870 27063-27296/com.nex3z.servicetest I/MyService﹕ count = 2 10-21 21:44:17.871 27063-27296/com.nex3z.servicetest I/MyService﹕ count = 3 10-21 21:44:18.802 27063-27063/com.nex3z.servicetest I/MyService﹕ Service is destroyed.
10-21 21:44:14.868  27063-27063/com.nex3z.servicetest I/MyService﹕ Service is created.
10-21 21:44:14.868  27063-27063/com.nex3z.servicetest I/MyService﹕ Service is started.
10-21 21:44:15.869  27063-27296/com.nex3z.servicetest I/MyService﹕ count = 1
10-21 21:44:16.870  27063-27296/com.nex3z.servicetest I/MyService﹕ count = 2
10-21 21:44:17.871  27063-27296/com.nex3z.servicetest I/MyService﹕ count = 3
10-21 21:44:18.802  27063-27063/com.nex3z.servicetest I/MyService﹕ Service is destroyed.

 可见Service能够正常地启动与停止。连续两次点击按钮启动Service,可以看到打印信息:
10-21 21:46:05.866 27733-27733/com.nex3z.servicetest I/MyService﹕ Service is created.
10-21 21:46:05.866 27733-27733/com.nex3z.servicetest I/MyService﹕ Service is started.
10-21 21:46:06.877 27733-28241/com.nex3z.servicetest I/MyService﹕ count = 1
10-21 21:46:07.638 27733-27733/com.nex3z.servicetest I/MyService﹕ Service is started.
10-21 21:46:07.868 27733-28241/com.nex3z.servicetest I/MyService﹕ count = 2
10-21 21:46:05.866 27733-27733/com.nex3z.servicetest I/MyService﹕ Service is created. 10-21 21:46:05.866 27733-27733/com.nex3z.servicetest I/MyService﹕ Service is started. 10-21 21:46:06.877 27733-28241/com.nex3z.servicetest I/MyService﹕ count = 1 10-21 21:46:07.638 27733-27733/com.nex3z.servicetest I/MyService﹕ Service is started. 10-21 21:46:07.868 27733-28241/com.nex3z.servicetest I/MyService﹕ count = 2
10-21 21:46:05.866  27733-27733/com.nex3z.servicetest I/MyService﹕ Service is created.
10-21 21:46:05.866  27733-27733/com.nex3z.servicetest I/MyService﹕ Service is started.
10-21 21:46:06.877  27733-28241/com.nex3z.servicetest I/MyService﹕ count = 1
10-21 21:46:07.638  27733-27733/com.nex3z.servicetest I/MyService﹕ Service is started.
10-21 21:46:07.868  27733-28241/com.nex3z.servicetest I/MyService﹕ count = 2

由此可以看出,startService()首先会通过Service的onCreate()来生成Service,然后通过onStartCommand()来启动Service。重复启动同一个Service,onStartCommand()会被重复调用,而onCreate()只会执行一次。

2. 绑定Service

  在上面的例子中,Activity仅仅是控制了Service的启动和停止,如果要实现与Service之间的数据交换,就需要将Service与Activity进行绑定,由Service需要向Activity提供访问其自身数据的方法。

  新建一个Service,命名为MyBindService,其内容与[代码0-1]所示的MyService基本一致,仅仅是更改了TAG 并去掉了对count 的打印,如[代码2-1]所示。

public class MyBindService extends Service {
private static final String TAG = "MyBindService";
private int count;
private boolean quit;
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "Service is created.");
count = 0;
quit = false;
new Thread() {
@Override
public void run() {
while (!quit) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
count++;
}
}
}.start();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "Service is started.");
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
quit = true;
Log.i(TAG, "Service is destroyed.");
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
public class MyBindService extends Service { private static final String TAG = "MyBindService"; private int count; private boolean quit; @Override public void onCreate() { super.onCreate(); Log.i(TAG, "Service is created."); count = 0; quit = false; new Thread() { @Override public void run() { while (!quit) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } count++; } } }.start(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG, "Service is started."); return START_STICKY; } @Override public void onDestroy() { super.onDestroy(); quit = true; Log.i(TAG, "Service is destroyed."); } @Override public IBinder onBind(Intent intent) { return null; } }
public class MyBindService extends Service {

    private static final String TAG = "MyBindService";

    private int count;
    private boolean quit;

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i(TAG, "Service is created.");

        count = 0;
        quit = false;
        new Thread() {
            @Override
            public void run() {
                while (!quit) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    count++;
                }
            }
        }.start();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(TAG, "Service is started.");
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        quit = true;
        Log.i(TAG, "Service is destroyed.");
    }

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

  为了让MyBindService向MyActivity提供访问其自身数据的方法,需要确实地实现MyBindService的onBind()方法,并在MyActivity中对MyBindService进行绑定。

2.1. 实现onBind()方法

  虽然[代码2-1]所示的MyBindService中也实现了onBind()方法,但只是返回了一个null 值,没有实际意义。这里需要修改让onBind()返回一个IBinder对象,这个IBinder对象会在MyService(或其他组件)绑定MyBindService的时候,由MyBindService返回给MyService,MyService可以通过这个IBinder对象与MyBindService进行通信。

  实现IBinder时一般会直接继承Binder,它是IBinder的实现。这里实现的MyBinder如[代码2-2]所示,它提供了一个getCount()方法,返回了MyBindService中的count 。

public class MyBinder extends Binder {
public int getCount() {
return count;
}
}
public class MyBinder extends Binder { public int getCount() { return count; } }
public class MyBinder extends Binder {
    public int getCount() {
        return count;
    }
}

  接下来为MyBindService添加成员private MyBinder binder = new MyBinder(); ,并修改MyBindService的onBind()方法返回binder ,如[代码2-3]所示。
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "Service is binded.");
return binder;
}
@Override public IBinder onBind(Intent intent) { Log.i(TAG, "Service is binded."); return binder; }
@Override
public IBinder onBind(Intent intent) {
    Log.i(TAG, "Service is binded.");
    return binder;
}

   到这里便完成了MyBindService,完整代码如[代码2-4]所示。
public class MyBindService extends Service {
private static final String TAG = "MyBindService";
private int count;
private boolean quit;
private MyBinder binder = new MyBinder();
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "Service is created.");
count = 0;
quit = false;
new Thread() {
@Override
public void run() {
while (!quit) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
count++;
}
}
}.start();
}
public class MyBinder extends Binder {
public int getCount() {
return count;
}
}
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "Service is binded.");
return binder;
}
@Override
public boolean onUnbind(Intent intent) {
Log.i(TAG, "Service is unbinded.");
return true;
}
@Override
public void onDestroy() {
super.onDestroy();
quit = true;
Log.i(TAG, "Service is destroyed.");
}
}
public class MyBindService extends Service { private static final String TAG = "MyBindService"; private int count; private boolean quit; private MyBinder binder = new MyBinder(); @Override public void onCreate() { super.onCreate(); Log.i(TAG, "Service is created."); count = 0; quit = false; new Thread() { @Override public void run() { while (!quit) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } count++; } } }.start(); } public class MyBinder extends Binder { public int getCount() { return count; } } @Override public IBinder onBind(Intent intent) { Log.i(TAG, "Service is binded."); return binder; } @Override public boolean onUnbind(Intent intent) { Log.i(TAG, "Service is unbinded."); return true; } @Override public void onDestroy() { super.onDestroy(); quit = true; Log.i(TAG, "Service is destroyed."); } }
public class MyBindService extends Service {

    private static final String TAG = "MyBindService";

    private int count;
    private boolean quit;
    private MyBinder binder = new MyBinder();

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i(TAG, "Service is created.");

        count = 0;
        quit = false;
        new Thread() {
            @Override
            public void run() {
                while (!quit) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    count++;
                }
            }
        }.start();
    }

    public class MyBinder extends Binder {
        public int getCount() {
            return count;
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.i(TAG, "Service is binded.");
        return binder;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.i(TAG, "Service is unbinded.");
        return true;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        quit = true;
        Log.i(TAG, "Service is destroyed.");
    }
}

2.2. Service的绑定

   Service的绑定是通过bindService()实现的,其完整签名为:

public abstract boolean bindService (Intent service, ServiceConnection conn, int flags)
public abstract boolean bindService (Intent service, ServiceConnection conn, int flags)
public abstract boolean bindService (Intent service, ServiceConnection conn, int flags)

 其中service 指明所要绑定的Service,conn 是一个ServiceConnection对象,用于接收Service启动和停止的信息,flags 用于设置绑定的参数,比如是否在绑定时自动创建Service(0表示不自动创建,BIND_AUTO_CREATE 表示自动创建等,其他选项可以参考API文档)。

    为了完成绑定,需要实现bindService()参数中的ServiceConnection,它用于监听所绑定Service的连接状态:当连接成功时,将回调ServiceConnection对象的onServiceConnected()方法,Service中onBind()方法返回的IBinder会作为参数传递给onServiceConnected();当连接意外中断时,则回调onServiceDisconnected()。

    回到例子的具体实现上,首先为MyActivity添加成员private MyBinder binder = new MyBinder(); 用于在本地保存MyBindService返回的IBinder,然后实现ServiceConnection如[代码2-5]所示。

private ServiceConnection serviceConn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
binder = (MyBindService.MyBinder) iBinder;
Log.i(TAG, "Service is connected.");
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
Log.i(TAG, "Service is disconnected.");
}
};
private ServiceConnection serviceConn = new ServiceConnection() { @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { binder = (MyBindService.MyBinder) iBinder; Log.i(TAG, "Service is connected."); } @Override public void onServiceDisconnected(ComponentName componentName) { Log.i(TAG, "Service is disconnected."); } };
private ServiceConnection serviceConn = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
        binder = (MyBindService.MyBinder) iBinder;
        Log.i(TAG, "Service is connected.");
    }

    @Override
    public void onServiceDisconnected(ComponentName componentName) {
        Log.i(TAG, "Service is disconnected.");
    }
};

 这里onServiceConnected()将作为参数传递过来的iBinder 保存为本地的binder ,onServiceDisconnected()只进行了打印。

    在MyActivity中加入三个按钮:btnBindService 用于绑定MyBindService,btnStatus 用于读取MyBindService中count 的值,btnBindService 用于解绑MyBindService。最终结果如[代码2-6]所示。

public class MyActivity extends Activity {
private static final String TAG = "MyActivity";
private MyBindService.MyBinder binder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
final Intent bindServiceIntent = new Intent(this, MyBindService.class);
Button btnBindService = (Button)findViewById(R.id.btnBindService);
btnBindService.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
bindService(bindServiceIntent, serviceConn, Service.BIND_AUTO_CREATE);
}
});
Button btnStatus = (Button)findViewById(R.id.btnStatus);
btnStatus.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(MyActivity.this, "count = " + binder.getCount(),
Toast.LENGTH_SHORT).show();
Log.i(TAG, "count = " + binder.getCount());
}
});
Button btnUnbindService = (Button)findViewById(R.id.btnUnbindService);
btnUnbindService.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
unbindService(serviceConn);
}
});
}
private ServiceConnection serviceConn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
binder = (MyBindService.MyBinder) iBinder;
Log.i(TAG, "Service is connected.");
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
Log.i(TAG, "Service is disconnected.");
}
};
}
public class MyActivity extends Activity { private static final String TAG = "MyActivity"; private MyBindService.MyBinder binder; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_my); final Intent bindServiceIntent = new Intent(this, MyBindService.class); Button btnBindService = (Button)findViewById(R.id.btnBindService); btnBindService.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { bindService(bindServiceIntent, serviceConn, Service.BIND_AUTO_CREATE); } }); Button btnStatus = (Button)findViewById(R.id.btnStatus); btnStatus.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { Toast.makeText(MyActivity.this, "count = " + binder.getCount(), Toast.LENGTH_SHORT).show(); Log.i(TAG, "count = " + binder.getCount()); } }); Button btnUnbindService = (Button)findViewById(R.id.btnUnbindService); btnUnbindService.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { unbindService(serviceConn); } }); } private ServiceConnection serviceConn = new ServiceConnection() { @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { binder = (MyBindService.MyBinder) iBinder; Log.i(TAG, "Service is connected."); } @Override public void onServiceDisconnected(ComponentName componentName) { Log.i(TAG, "Service is disconnected."); } }; }
public class MyActivity extends Activity {
    private static final String TAG = "MyActivity";

    private MyBindService.MyBinder binder;

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

        final Intent bindServiceIntent = new Intent(this, MyBindService.class);

        Button btnBindService = (Button)findViewById(R.id.btnBindService);
        btnBindService.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                bindService(bindServiceIntent, serviceConn, Service.BIND_AUTO_CREATE);
            }
        });

        Button btnStatus = (Button)findViewById(R.id.btnStatus);
        btnStatus.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(MyActivity.this, "count = " + binder.getCount(), 
                               Toast.LENGTH_SHORT).show();
                Log.i(TAG, "count = " + binder.getCount());
            }
        });

        Button btnUnbindService = (Button)findViewById(R.id.btnUnbindService);
        btnUnbindService.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                unbindService(serviceConn);
            }
        });
    }

    private ServiceConnection serviceConn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            binder = (MyBindService.MyBinder) iBinder;
            Log.i(TAG, "Service is connected.");
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            Log.i(TAG, "Service is disconnected.");
        }
    };
}

其中第17行通过bindService(bindServiceIntent, serviceConn, Service.BIND_AUTO_CREATE); ,使MyActivity与bindServiceIntent 所指定的MyBindService进行了绑定,由serviceConn 管理连接,Service.BIND_AUTO_CREATE 表示在绑定时自动创建Service。

   运行MyActivity,点击btnBindService 绑定MyBindService后,点击btnStatus 读取MyBindService中count 的数值,再点击btnBindService 解除绑定,得到打印信息:

10-18 18:34:38.874 4492-4492/com.nex3z.servicetest I/MyBindService﹕ Service is created.
10-18 18:34:38.894 4492-4492/com.nex3z.servicetest I/MyBindService﹕ Service is binded.
10-18 18:34:38.894 4492-4492/com.nex3z.servicetest I/MyActivity﹕ Service is connected.
10-18 18:34:41.547 4492-4492/com.nex3z.servicetest I/MyActivity﹕ count = 3
10-18 18:34:44.260 4492-4492/com.nex3z.servicetest I/MyActivity﹕ count = 6
10-18 18:34:46.762 4492-4492/com.nex3z.servicetest I/MyBindService﹕ Service is unbinded.
10-18 18:34:46.762 4492-4492/com.nex3z.servicetest I/MyBindService﹕ Service is destroyed.
10-18 18:34:38.874 4492-4492/com.nex3z.servicetest I/MyBindService﹕ Service is created. 10-18 18:34:38.894 4492-4492/com.nex3z.servicetest I/MyBindService﹕ Service is binded. 10-18 18:34:38.894 4492-4492/com.nex3z.servicetest I/MyActivity﹕ Service is connected. 10-18 18:34:41.547 4492-4492/com.nex3z.servicetest I/MyActivity﹕ count = 3 10-18 18:34:44.260 4492-4492/com.nex3z.servicetest I/MyActivity﹕ count = 6 10-18 18:34:46.762 4492-4492/com.nex3z.servicetest I/MyBindService﹕ Service is unbinded. 10-18 18:34:46.762 4492-4492/com.nex3z.servicetest I/MyBindService﹕ Service is destroyed.
10-18 18:34:38.874    4492-4492/com.nex3z.servicetest I/MyBindService﹕ Service is created.
10-18 18:34:38.894    4492-4492/com.nex3z.servicetest I/MyBindService﹕ Service is binded.
10-18 18:34:38.894    4492-4492/com.nex3z.servicetest I/MyActivity﹕ Service is connected.
10-18 18:34:41.547    4492-4492/com.nex3z.servicetest I/MyActivity﹕ count = 3
10-18 18:34:44.260    4492-4492/com.nex3z.servicetest I/MyActivity﹕ count = 6
10-18 18:34:46.762    4492-4492/com.nex3z.servicetest I/MyBindService﹕ Service is unbinded.
10-18 18:34:46.762    4492-4492/com.nex3z.servicetest I/MyBindService﹕ Service is destroyed.

可见,MyActivity可以获取到MyBindService中count 的数值。在绑定服务时,首先执行的是Service中的onCreate()和onBind()方法,然后才会回调在绑定Service时所指定的ServiceConnection对象的onServiceConnected()方法。解除绑定时,onServiceDisconnected()方法没有执行,这是因为上面的例子是通过unBindService()来主动解除绑定的,onServiceConnected()只有在Service所在的宿主进程意外终止导致连接断开时才会被调用。

3. IntentService

   在前面的例子中,Activity所启动的Service与Activity在同一个进程中运行,而且Service也不会自动为自己的业务新建线程,如果在Service中直接处理耗时任务,就可能导致应用程序无响应(Application Not Responding,ANR )。所以在[代码0-1]和[代码2-4]中,都是在Service的onCreate()中手动新建了线程对count 进行计数。

   IntentService是Service的子类,顾名思义,客户端使用startService()通过Intent请求启动IntentService,IntentService使用队列对客户端发来的Intent进行管理,并开启新线程来处理Intent。

   一个例子如[代码3-1]所示,IntentService为onBind()和onStartCommand()提供了默认实现,所以只重写了onHandleEvent()。MyIntentService进行了30秒的计时和打印。

public class MyIntentService extends IntentService {
private static final String TAG = "MyIntentService";
public MyIntentService() {
super("MyIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
Log.i(TAG, "Count start.");
int count = 1;
while (count <= 30) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.i(TAG, "count = " + count);
count++;
}
Log.i(TAG, "Count complete.");
}
}
public class MyIntentService extends IntentService { private static final String TAG = "MyIntentService"; public MyIntentService() { super("MyIntentService"); } @Override protected void onHandleIntent(Intent intent) { Log.i(TAG, "Count start."); int count = 1; while (count <= 30) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } Log.i(TAG, "count = " + count); count++; } Log.i(TAG, "Count complete."); } }
public class MyIntentService extends IntentService {

    private static final String TAG = "MyIntentService";

    public MyIntentService() {
        super("MyIntentService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        Log.i(TAG, "Count start.");
        int count = 1;
        while (count <= 30) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Log.i(TAG, "count = " + count);
            count++;
        }
        Log.i(TAG, "Count complete.");
    }

}

  为了与IntentService对比,建立如[代码3-2]所示的普通Service,CounterService同样是进行30秒的计时和打印,但没有手动新建线程。
public class CounterService extends Service {
private static final String TAG = "CounterService";
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "Count start.");
int count = 1;
while (count <= 30) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.i(TAG, "count = " + count);
count++;
}
Log.i(TAG, "Count complete.");
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
public class CounterService extends Service { private static final String TAG = "CounterService"; @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG, "Count start."); int count = 1; while (count <= 30) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } Log.i(TAG, "count = " + count); count++; } Log.i(TAG, "Count complete."); return START_STICKY; } @Override public IBinder onBind(Intent intent) { return null; } }
public class CounterService extends Service {

    private static final String TAG = "CounterService";

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(TAG, "Count start.");
        int count = 1;
        while (count <= 30) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Log.i(TAG, "count = " + count);
            count++;
        }
        Log.i(TAG, "Count complete.");
        return START_STICKY;
    }

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

  执行MyIntentService,打印结果如下:
...
10-25 15:59:29.529 6271-6990/com.nex3z.servicetest I/MyIntentService﹕ count = 27
10-25 15:59:30.530 6271-6990/com.nex3z.servicetest I/MyIntentService﹕ count = 28
10-25 15:59:31.541 6271-6990/com.nex3z.servicetest I/MyIntentService﹕ count = 29
10-25 15:59:31.541 6271-6990/com.nex3z.servicetest I/MyIntentService﹕ Count complete.
... 10-25 15:59:29.529 6271-6990/com.nex3z.servicetest I/MyIntentService﹕ count = 27 10-25 15:59:30.530 6271-6990/com.nex3z.servicetest I/MyIntentService﹕ count = 28 10-25 15:59:31.541 6271-6990/com.nex3z.servicetest I/MyIntentService﹕ count = 29 10-25 15:59:31.541 6271-6990/com.nex3z.servicetest I/MyIntentService﹕ Count complete.
...
10-25 15:59:29.529    6271-6990/com.nex3z.servicetest I/MyIntentService﹕ count = 27
10-25 15:59:30.530    6271-6990/com.nex3z.servicetest I/MyIntentService﹕ count = 28
10-25 15:59:31.541    6271-6990/com.nex3z.servicetest I/MyIntentService﹕ count = 29
10-25 15:59:31.541    6271-6990/com.nex3z.servicetest I/MyIntentService﹕ Count complete.

 可见MyIntentService顺利完成了计时。而执行CounterService时,打印结果如下:
...
10-25 16:02:02.128 6271-6271/com.nex3z.servicetest I/CounterService﹕ count = 19
10-25 16:02:03.129 6271-6276/com.nex3z.servicetest I/dalvikvm﹕ threadid=3: reacting to signal 3
10-25 16:02:03.159 6271-6271/com.nex3z.servicetest I/CounterService﹕ count = 20
10-25 16:02:03.159 6271-6276/com.nex3z.servicetest I/dalvikvm﹕ Wrote stack traces to '/data/anr/traces.txt'
10-25 16:02:04.160 6271-6271/com.nex3z.servicetest I/CounterService﹕ count = 21
10-25 16:02:05.161 6271-6271/com.nex3z.servicetest I/CounterService﹕ count = 22
10-25 16:02:06.162 6271-6271/com.nex3z.servicetest I/CounterService﹕ count = 23
10-25 16:02:07.153 6271-6271/com.nex3z.servicetest I/CounterService﹕ count = 24
10-25 16:02:07.544 6271-6271/com.nex3z.servicetest A/libc﹕ Fatal signal 6 (SIGABRT) at 0x0000027b (code=0), thread 6271 (x3z.servicetest)
... 10-25 16:02:02.128 6271-6271/com.nex3z.servicetest I/CounterService﹕ count = 19 10-25 16:02:03.129 6271-6276/com.nex3z.servicetest I/dalvikvm﹕ threadid=3: reacting to signal 3 10-25 16:02:03.159 6271-6271/com.nex3z.servicetest I/CounterService﹕ count = 20 10-25 16:02:03.159 6271-6276/com.nex3z.servicetest I/dalvikvm﹕ Wrote stack traces to '/data/anr/traces.txt' 10-25 16:02:04.160 6271-6271/com.nex3z.servicetest I/CounterService﹕ count = 21 10-25 16:02:05.161 6271-6271/com.nex3z.servicetest I/CounterService﹕ count = 22 10-25 16:02:06.162 6271-6271/com.nex3z.servicetest I/CounterService﹕ count = 23 10-25 16:02:07.153 6271-6271/com.nex3z.servicetest I/CounterService﹕ count = 24 10-25 16:02:07.544 6271-6271/com.nex3z.servicetest A/libc﹕ Fatal signal 6 (SIGABRT) at 0x0000027b (code=0), thread 6271 (x3z.servicetest)
...
10-25 16:02:02.128    6271-6271/com.nex3z.servicetest I/CounterService﹕ count = 19
10-25 16:02:03.129    6271-6276/com.nex3z.servicetest I/dalvikvm﹕ threadid=3: reacting to signal 3
10-25 16:02:03.159    6271-6271/com.nex3z.servicetest I/CounterService﹕ count = 20
10-25 16:02:03.159    6271-6276/com.nex3z.servicetest I/dalvikvm﹕ Wrote stack traces to '/data/anr/traces.txt'
10-25 16:02:04.160    6271-6271/com.nex3z.servicetest I/CounterService﹕ count = 21
10-25 16:02:05.161    6271-6271/com.nex3z.servicetest I/CounterService﹕ count = 22
10-25 16:02:06.162    6271-6271/com.nex3z.servicetest I/CounterService﹕ count = 23
10-25 16:02:07.153    6271-6271/com.nex3z.servicetest I/CounterService﹕ count = 24
10-25 16:02:07.544    6271-6271/com.nex3z.servicetest A/libc﹕ Fatal signal 6 (SIGABRT) at 0x0000027b (code=0), thread 6271 (x3z.servicetest)

 在CounterService开始执行后,应用便会失去响应,执行时间过长还会出现ANR。

4. AIDL Service

  如前所述,通过绑定Service可以实现Service与其他组件之间的数据交换,但Android系统中的进程之间一般无法直接交换数据,为了让Service能够跨进程与其他组件进行通信,就需要使用AIDL(Android Interface Definition Language)。

  下面依旧通过一个例子说明AIDL Service的使用。例子内容与前面类似,依旧是在Service中进行计数,由Activity读取Service中计数的值,不过这次Activity与Service不在处于同一进程,Service需要定义一个远程调用接口,并提供实现,Activity远程调用Service的接口,与Service进行通信。

4.1. 编写AIDL文件

  AIDL用于定义远程接口,其详细使用方法可以参考官方文档,这里只是通过例子给出一个简单的示范,建立一个MyAIDLInterface.aidl文件,如[代码4-1]所示。

interface IMyAidlInterface {
int getCount();
}
interface IMyAidlInterface { int getCount(); }
interface IMyAidlInterface {
    int getCount();
}

可以看出,AIDL的语法与Java类似,上面的例子声明了一个getCount()方法,该方法返回一个int型的值。如果使用Eclipse,上面的AIDL文件保存之后,就可以在gen目录下找到一个自动生成的MyAidlInterface.java文件;如果使用的是Android Studio,则需要先“Make Project”,然后就可以在build/generated/source/aidl下找到自动生成的MyAidlInterface.java文件。MyAidlInterface包含一个内部类Stub,该内部类继承了Binder,并实现了IMyAidlInterface。由于Stub继承了Binder,可以将Stub的实例作为Service的onBind()方法的返回值,提供给远程组件;由于与Stub实现了IMyAidlInterface,使得Stub可以向远程组件提供MyAIDLInterface.aidl中定义的接口。

4.2. 建立Service

  MyAIDLInterface.aidl文件中声明了接口getCount(),接下来就要给出getCount()的实现,如代码[4-2]所示。

public class MyAidlServiceBinder extends IMyAidlInterface.Stub {
@Override
public int getCount() throws RemoteException {
return count;
}
}
public class MyAidlServiceBinder extends IMyAidlInterface.Stub { @Override public int getCount() throws RemoteException { return count; } }
public class MyAidlServiceBinder extends IMyAidlInterface.Stub {

    @Override
    public int getCount() throws RemoteException {
        return count;
    }
}

 声明MyAidlServiceBinder继承IMyAidlInterface.Stub,并实现getCount()返回count ——Service中的计数值。

  然后为Service添加成员private MyAidlServiceBinder binder; ,并通过onBind()返回binder ,如[代码4-3]所示。

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

   最终得到的Service如[代码4-4]所示:
public class MyAidlService extends Service {
private static final String TAG = "MyAidlActivity";
private int count;
private boolean quit;
private MyAidlServiceBinder binder;
public class MyAidlServiceBinder extends IMyAidlInterface.Stub {
@Override
public int getCount() throws RemoteException {
return count;
}
}
@Override
public IBinder onBind(Intent intent) {
return binder;
}
@Override
public void onCreate() {
super.onCreate();
Log.i(TAG, "Service is created.");
binder = new MyAidlServiceBinder();
count = 0;
quit = false;
new Thread() {
@Override
public void run() {
while (!quit) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
count++;
}
}
}.start();
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i(TAG, "Service is destroyed.");
}
}
public class MyAidlService extends Service { private static final String TAG = "MyAidlActivity"; private int count; private boolean quit; private MyAidlServiceBinder binder; public class MyAidlServiceBinder extends IMyAidlInterface.Stub { @Override public int getCount() throws RemoteException { return count; } } @Override public IBinder onBind(Intent intent) { return binder; } @Override public void onCreate() { super.onCreate(); Log.i(TAG, "Service is created."); binder = new MyAidlServiceBinder(); count = 0; quit = false; new Thread() { @Override public void run() { while (!quit) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } count++; } } }.start(); } @Override public void onDestroy() { super.onDestroy(); Log.i(TAG, "Service is destroyed."); } }
public class MyAidlService extends Service {
    private static final String TAG = "MyAidlActivity";

    private int count;
    private boolean quit;
    private MyAidlServiceBinder binder;

    public class MyAidlServiceBinder extends IMyAidlInterface.Stub {

        @Override
        public int getCount() throws RemoteException {
            return count;
        }
    }

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

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i(TAG, "Service is created.");

        binder = new MyAidlServiceBinder();

        count = 0;
        quit = false;
        new Thread() {
            @Override
            public void run() {
                while (!quit) {

                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    count++;
                }
            }
        }.start();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.i(TAG, "Service is destroyed.");
    }
}

 在onCreate()中,通过binder = new MyAidlServiceBinder(); 创建了MyAidlServiceBinder的实例,供onBind()作为返回值。此时可以先运行MyAidlService,供后面MyActivity进行远程调用。

4.3. 远程调用

   依旧使用MyActivity远程调用MyAidlService。为MyActivity添加成员private IMyAidlInterface aidlService; ,添加按钮btnBindAidlService  和btnUnbindAidlService 分别用于绑定Service和解绑Service,如[代码4-5]所示。

final Intent bindAidlServiceIntent = new Intent(this, MyAidlService.class);
Button btnBindAidlService = (Button)findViewById(R.id.btnBindAidlService);
btnBindAidlService.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
bindService(bindAidlServiceIntent, aidlServiceConn, Service.BIND_AUTO_CREATE);
}
});
Button btnUnbindAidlService = (Button)findViewById(R.id.btnUnbindAidlService);
btnUnbindAidlService.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
unbindService(aidlServiceConn);
}
});
final Intent bindAidlServiceIntent = new Intent(this, MyAidlService.class); Button btnBindAidlService = (Button)findViewById(R.id.btnBindAidlService); btnBindAidlService.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { bindService(bindAidlServiceIntent, aidlServiceConn, Service.BIND_AUTO_CREATE); } }); Button btnUnbindAidlService = (Button)findViewById(R.id.btnUnbindAidlService); btnUnbindAidlService.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { unbindService(aidlServiceConn); } });
final Intent bindAidlServiceIntent = new Intent(this, MyAidlService.class);

Button btnBindAidlService = (Button)findViewById(R.id.btnBindAidlService);
btnBindAidlService.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View view) {
        bindService(bindAidlServiceIntent, aidlServiceConn, Service.BIND_AUTO_CREATE);
    }
});

Button btnUnbindAidlService = (Button)findViewById(R.id.btnUnbindAidlService);
btnUnbindAidlService.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View view) {
        unbindService(aidlServiceConn);
    }
});

可以看出,绑定和解绑AIDL Service的流程与绑定普通Service类似,第7行中绑定Service时使用的aidlServiceConn 如[代码4-6]所示。
private ServiceConnection aidlServiceConn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
aidlService = IMyAidlInterface.Stub.asInterface(iBinder);
Log.i(TAG, "AIDL Service is connected.");
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
aidlService = null;
Log.i(TAG, "AIDL Service is disconnected.");
}
};
private ServiceConnection aidlServiceConn = new ServiceConnection() { @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { aidlService = IMyAidlInterface.Stub.asInterface(iBinder); Log.i(TAG, "AIDL Service is connected."); } @Override public void onServiceDisconnected(ComponentName componentName) { aidlService = null; Log.i(TAG, "AIDL Service is disconnected."); } };
private ServiceConnection aidlServiceConn = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
        aidlService = IMyAidlInterface.Stub.asInterface(iBinder);
        Log.i(TAG, "AIDL Service is connected.");
    }

    @Override
    public void onServiceDisconnected(ComponentName componentName) {
        aidlService = null;
        Log.i(TAG, "AIDL Service is disconnected.");
    }
};

在onServiceConnected()的第4行,把通过参数传递过来的iBinder 保存到本地。注意这里使用了IMyAidlInterface.Stub.asInterface(iBinder) ,而不是直接像[代码2-6]中那样直接对iBinder 进行类型转换,这是因为绑定远程Service的ServiceConnection不能直接获取Service中onBind()方法返回的对象,而只能通过IMyAidlInterface.Stub.asInterface(iBinder) 获取onBind()返回对象的代理。

   为MyActivity添加按钮btnStatusAidl 用于读取并打印MyAidlService中的count 值,如代码[4-7]所示。

Button btnStatusAidl = (Button)findViewById(R.id.btnStatusAidl);
btnStatusAidl.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
try {
Toast.makeText(MyActivity.this, "count = " + aidlService.getCount(), Toast.LENGTH_SHORT).show();
Log.i(TAG, "count = " + aidlService.getCount());
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
Button btnStatusAidl = (Button)findViewById(R.id.btnStatusAidl); btnStatusAidl.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { try { Toast.makeText(MyActivity.this, "count = " + aidlService.getCount(), Toast.LENGTH_SHORT).show(); Log.i(TAG, "count = " + aidlService.getCount()); } catch (RemoteException e) { e.printStackTrace(); } } });
Button btnStatusAidl = (Button)findViewById(R.id.btnStatusAidl);
btnStatusAidl.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View view) {
        try {
            Toast.makeText(MyActivity.this, "count = " + aidlService.getCount(), Toast.LENGTH_SHORT).show();
            Log.i(TAG, "count = " + aidlService.getCount());
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
});

直接通过aidlService.getCount() 就实现了远程调用,获取了MyAidlService中count 的值,打印结果如下:
...
10-25 17:15:00.780 9505-9505/com.nex3z.servicetest I/MyActivity﹕ count = 2
10-25 17:15:02.392 9505-9505/com.nex3z.servicetest I/MyActivity﹕ count = 4
... 10-25 17:15:00.780 9505-9505/com.nex3z.servicetest I/MyActivity﹕ count = 2 10-25 17:15:02.392 9505-9505/com.nex3z.servicetest I/MyActivity﹕ count = 4
...
10-25 17:15:00.780    9505-9505/com.nex3z.servicetest I/MyActivity﹕ count = 2
10-25 17:15:02.392    9505-9505/com.nex3z.servicetest I/MyActivity﹕ count = 4

可见,MyActivity成功与MyAidlService进行了通信。