1. Service
1.1 知识点
(1)掌握Service与Activity的区别;
(2)掌握Service的定义及使用;
(3)可以使用ServiceConnection 接口绑定一个Service;
(4)了解系统提供的Service程序。
1.2 具体内容
Service是Android四大组件之一,和Activity最大的区别在于一个有界面,一个没有界面。
如果在程序中要实现Services的操作的话,需要定义一个Services类的子类,并且有这个子类复写相应的操作方法。
范例:定义后台服务
对于后台服务就是指我们Services程序,肯定是没有界面去显示的,就是在后台运行。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/start"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="启动Services" />
<Button
android:id="@+id/stop"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="停止Services" />
</LinearLayout>
关键肯定是要编写我们Services程序。
package com.example.servicesproject;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
public class MyServices extends Service {
@Override
public IBinder onBind(Intent intent) {//绑定Activity
return null;
}
@Override
public void onCreate() {//创建时调用
System.out.println("============Service被创建============");
}
@Override
public void onDestroy() {//销毁时调用
System.out.println("============Service被销毁============");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {//开始Services
System.out.println("============Service启动============intent = " + intent + "startId="+startId);
return Service.START_CONTINUATION_MASK;//表示Service继续执行
}
}
对于Service,本身并没有界面,只是提供了一个后台的操作,本身需要依靠Activity程序去启动。
package com.example.servicesproject;
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 ServicesActivity extends Activity {
private Button start = null;
private Button stop = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.activity_services);
this.start = (Button) super.findViewById(R.id.start);
this.stop = (Button) super.findViewById(R.id.stop);
this.start.setOnClickListener(new StartOnClickListenerImpl());
this.stop.setOnClickListener(new StopOnClickListenerImpl());
}
private class StartOnClickListenerImpl implements OnClickListener {
public void onClick(View v) {
//启动Service
ServicesActivity.this.startService(new Intent(ServicesActivity.this,MyServices.class));
}
}
private class StopOnClickListenerImpl implements OnClickListener {
public void onClick(View v) {
//停止Service
ServicesActivity.this.stopService(new Intent(ServicesActivity.this,MyServices.class));
}
}
}
通过Activity程序去控制Service的开始和停止,既然Service程序是一个没有界面的Activity,那么肯定也需要在AndroidMainFest.xml里面进行配置。
<service
android:name="com.example.servicesproject.MyServices"></service>
如果说一个Activity和Service要进行绑定的话,必须要使用到ServiceConnection这个接口,这个接口中有两个方法,一个是建立连接的时候使用,第二个是取消连接的时候使用, 但是一定要注意,连接是触发的操作中,还有一个IBinder接口对象。
既然IBinder是一个接口,那么这个接口中肯定存在大量的抽象方法,所以按照正常的思路肯定是会去覆写IBinder接口中所有的抽象方法,现在我们可以继承它,我们就可以覆写指定的方法。
package com.example.servicesproject;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
public class MyServices extends Service {
private IBinder myIBinder = new Binder(){
@Override
public String getInterfaceDescriptor() {//取得接口的描述信息
return "MyServices.class";
}
};
@Override
public IBinder onBind(Intent intent) {//绑定Activity
System.out.println("===========onBind==========intent="+intent);
return myIBinder;
}
@Override
public boolean onUnbind(Intent intent) {//解除绑定
System.out.println("===========onUnbind==========intent="+intent);
return super.onUnbind(intent);
}
@Override
public void onRebind(Intent intent) {
System.out.println("===========onRebind==========intent="+intent);
super.onRebind(intent);
}
@Override
public void onCreate() {//创建时调用
System.out.println("============Service被创建============");
}
@Override
public void onDestroy() {//销毁时调用
System.out.println("============Service被销毁============");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {//开始Services
System.out.println("============Service启动============intent = " + intent + "startId="+startId);
return Service.START_CONTINUATION_MASK;//表示Service继续执行
}
}
而后的Activity程序中增加一些操作按钮。
package com.example.servicesproject;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class ServicesActivity extends Activity {
private Button start = null;
private Button stop = null;
private Button bind = null;
private Button unbind = null;
private ServiceConnection serviceConnection = new ServiceConnection(){
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
try {
System.out.println("==========连接到Service==========" + service.getInterfaceDescriptor());
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
System.out.println("=================取消Service=============");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.activity_services);
this.start = (Button) super.findViewById(R.id.start);
this.stop = (Button) super.findViewById(R.id.stop);
this.start.setOnClickListener(new StartOnClickListenerImpl());
this.stop.setOnClickListener(new StopOnClickListenerImpl());
this.bind =(Button) super.findViewById(R.id.bind);
this.unbind = (Button) super.findViewById(R.id.unbind);
this.bind.setOnClickListener(new BindOnClickListenerImpl());
this.unbind.setOnClickListener(new UNBindOnClickListenerImpl());
}
private class StartOnClickListenerImpl implements OnClickListener {
public void onClick(View v) {
//启动Service
ServicesActivity.this.startService(new Intent(ServicesActivity.this,MyServices.class));
}
}
private class StopOnClickListenerImpl implements OnClickListener {
public void onClick(View v) {
//停止Service
ServicesActivity.this.stopService(new Intent(ServicesActivity.this,MyServices.class));
}
}
private class BindOnClickListenerImpl implements OnClickListener{
@Override
public void onClick(View v) {
//进行Service绑定
ServicesActivity.this.bindService(new Intent(ServicesActivity.this,MyServices.class), ServicesActivity.this.serviceConnection, Context.BIND_AUTO_CREATE);
}
}
private class UNBindOnClickListenerImpl implements OnClickListener{
@Override
public void onClick(View v) {
//取消绑定
ServicesActivity.this.unbindService(ServicesActivity.this.serviceConnection);
}
}
}
此时的Activity程序就已经完成,下面我们来观察运行消息打印的流程。
·启动Service
01-27 01:07:36.243: INFO/System.out(487): ============Service被创建============
01-27 01:07:36.243: INFO/System.out(487): ============Service启动============intent = Intent { cmp=com.example.servicesproject/.MyServices }startId=1
·绑定Service
01-27 01:08:29.583: INFO/System.out(487): ===========onBind==========intent=Intent { cmp=com.example.servicesproject/.MyServices }
01-27 01:08:29.583: INFO/System.out(487): ==========连接到Service==========MyServices.class
通过打印,可以清楚的发现,出现了onBind之后,会返回到ServiceConnection中执行onServiceConnected()方法。
·如果不启动直接绑定
01-27 01:11:22.652: INFO/System.out(877): ============Service被创建============
01-27 01:11:22.652: INFO/System.out(877): ===========onBind==========intent=Intent { cmp=com.example.servicesproject/.MyServices }
01-27 01:11:22.672: INFO/System.out(877): ==========连接到Service==========MyServices.class
如果直接绑定,则直接调用OnCreate()、onBind()、ServiceConnection中的onServiceConnected()
·不停止,直接退出
01-27 01:12:39.733: I/System.out(877): ===========onUnbind==========intent=Intent { cmp=com.example.servicesproject/.MyServices }
01-27 01:12:39.733: I/System.out(877): ============Service被销毁============
不停止直接退出,会先取消绑定,再销毁。
·返回到Activity,同时再设置绑定
01-27 01:13:50.274: INFO/System.out(877): ============Service被创建============
01-27 01:13:50.274: INFO/System.out(877): ===========onBind==========intent=Intent { cmp=com.example.servicesproject/.MyServices }
01-27 01:13:50.292: INFO/System.out(877): ==========连接到Service==========MyServices.class
·解除绑定
01-27 01:14:19.702: INFO/System.out(877): ===========onUnbind==========intent=Intent { cmp=com.example.servicesproject/.MyServices }
01-27 01:14:19.702: INFO/System.out(877): ============Service被销毁============
也就是说,我们在操作之中,主应该注意的方法是:OnCreate()、onBind()、onUnbind(),onDestroy()。
虽然,以上的程序已经进行了绑定,但是还存在一个问题 。
定义一个空的接口,作为一个标识。
public interface IService {
}
此接口中不需要编写任何的操作方法。
package com.example.servicesproject;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
public class MyServices extends Service {
private IBinder myIBinder = new IBinderImpl();
private class IBinderImpl extends Binder implements IService{
@Override
public String getInterfaceDescriptor() {//取得接口信息
return "MyServices.class";
}
}
@Override
public IBinder onBind(Intent intent) {//绑定Activity
System.out.println("===========onBind==========intent="+intent);
return myIBinder;
}
@Override
public boolean onUnbind(Intent intent) {//解除绑定
System.out.println("===========onUnbind==========intent="+intent);
return super.onUnbind(intent);
}
@Override
public void onRebind(Intent intent) {
System.out.println("===========onRebind==========intent="+intent);
super.onRebind(intent);
}
@Override
public void onCreate() {//创建时调用
System.out.println("============Service被创建============");
}
@Override
public void onDestroy() {//销毁时调用
System.out.println("============Service被销毁============");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {//开始Services
System.out.println("============Service启动============intent = " + intent + "startId="+startId);
return Service.START_CONTINUATION_MASK;//表示Service继续执行
}
}
大家一定要记住,IBinderImpl一定要是Binder和IService共同子类。
package com.example.servicesproject;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class ServicesActivity extends Activity {
private Button start = null;
private Button stop = null;
private Button bind = null;
private Button unbind = null;
private IService service = null;
private ServiceConnection serviceConnection = new ServiceConnectionImpl();
private class ServiceConnectionImpl implements ServiceConnection{
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
try {
System.out.println("==========连接到Service==========" + service.getInterfaceDescriptor());
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
System.out.println("=================取消Service=============");
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.activity_services);
this.start = (Button) super.findViewById(R.id.start);
this.stop = (Button) super.findViewById(R.id.stop);
this.start.setOnClickListener(new StartOnClickListenerImpl());
this.stop.setOnClickListener(new StopOnClickListenerImpl());
this.bind =(Button) super.findViewById(R.id.bind);
this.unbind = (Button) super.findViewById(R.id.unbind);
this.bind.setOnClickListener(new BindOnClickListenerImpl());
this.unbind.setOnClickListener(new UNBindOnClickListenerImpl());
}
private class StartOnClickListenerImpl implements OnClickListener {
public void onClick(View v) {
//启动Service
ServicesActivity.this.startService(new Intent(ServicesActivity.this,MyServices.class));
}
}
private class StopOnClickListenerImpl implements OnClickListener {
public void onClick(View v) {
//停止Service
ServicesActivity.this.stopService(new Intent(ServicesActivity.this,MyServices.class));
}
}
private class BindOnClickListenerImpl implements OnClickListener{
@Override
public void onClick(View v) {
//进行Service绑定
ServicesActivity.this.bindService(new Intent(ServicesActivity.this,MyServices.class), ServicesActivity.this.serviceConnection, Context.BIND_AUTO_CREATE);
}
}
private class UNBindOnClickListenerImpl implements OnClickListener{
@Override
public void onClick(View v) {
if(null != ServicesActivity.this.service){
//取消绑定
ServicesActivity.this.unbindService(ServicesActivity.this.serviceConnection);
ServicesActivity.this.service = null;
}
}
}
}
关键就是IBinder需要继承Binder还需要实现我们定义的空的接口。
·操作系统服务:服务的概念就是运行在后台之中,而且android之中为了方便的系统运行,也有多种服务提供给开发者使用。
范例:剪贴板服务
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
如果需要取得系统服务,需要使用getSystemService(服务标记);
package com.example.contextservice;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.text.ClipboardManager;
public class ContextServiceActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.activity_context_service);
ClipboardManager clipboardManager = (ClipboardManager)super.getSystemService(Context.CLIPBOARD_SERVICE);//取得剪贴板服务
clipboardManager.setText("毛栗子");
}
}
这边就是直接使用了后台提供的服务。
范例:取得正在运行的Activity程序信息
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView
android:id="@+id/aclist"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
肯定是需要通过Activity程序取得所有信息并在ListView中显示。
package com.example.activityrun;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import android.app.Activity;
import android.app.ActivityManager;
import android.content.Context;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
public class MainActivity extends Activity {
private ListView aclist = null;
private ListAdapter adapter = null;
private List<String> all = new ArrayList<String>();
private List<ActivityManager.RunningTaskInfo> allTaskInfo = null;//所有任务信息
private ActivityManager activityManager = null;//ActivityManager对象
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.activity_main);
this.aclist = (ListView) super.findViewById(R.id.aclist);
this.activityManager = (ActivityManager)super.getSystemService(Context.ACTIVITY_SERVICE);
this.listActivity();
}
public void listActivity(){
this.allTaskInfo = this.activityManager.getRunningTasks(30);//取回30笔任务数据
Iterator<ActivityManager.RunningTaskInfo> it = this.allTaskInfo.iterator();
while(it.hasNext()){
ActivityManager.RunningTaskInfo task = it.next();
this.all.add("【ID】"+task.id+"【NAME】"+task.baseActivity.getClassName());
}
this.adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,this.all);
this.aclist.setAdapter(this.adapter);
}
}
需要配置权限:
<uses-permission android:name="android.permission.GET_TASKS"/>
如果说要取得服务信息,则直接修改以上的程序就可以了。如果是要取得所有的进程信息,我们也只需要修改以上的程序。
范例:取得网络信息
如果要获取手机讯息,我们肯定也需要使用列表完成显示。
package com.example.activityrun;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.telephony.TelephonyManager;
import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
public class MainActivity extends Activity {
private ListView telinfo = null;
private ListAdapter adapter = null;
private List<String> all = new ArrayList<String>();
private TelephonyManager telephonyManager = null;//ActivityManager对象
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.activity_main);
this.telinfo = (ListView) super.findViewById(R.id.aclist);
this.telephonyManager = (TelephonyManager)super.getSystemService(Context.TELEPHONY_SERVICE);
this.listActivity();
}
public void listActivity(){
this.all.add(this.telephonyManager.getLine1Number()==null?"没有手机号码":"手机号:"+this.telephonyManager.getLine1Number());
this.all.add(this.telephonyManager.getNetworkOperatorName()== null?"没有移动服务商":"移动服务商:"+this.telephonyManager.getNetworkOperatorName());
if(this.telephonyManager.getPhoneType() == TelephonyManager.NETWORK_TYPE_CDMA){
this.all.add("移动网络:CDMA");
}else if(this.telephonyManager.getPhoneType() == TelephonyManager.NETWORK_TYPE_GPRS){
this.all.add("移动网络:GPRS");
}else{
this.all.add("移动网络:未知");
}
this.all.add("是否漫游:"+(this.telephonyManager.isNetworkRoaming()?"是漫游":"非漫游"));
this.adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,this.all);
this.telinfo.setAdapter(this.adapter);
}
}
权限:
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
范例:操作WIFI
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/mag"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/openWIFI"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="打开WIFI"/>
<Button
android:id="@+id/closeWIFI"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="关闭WIFI"/>
<Button
android:id="@+id/selectState"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="检查WIFI状态"/>
</LinearLayout>
package com.example.activityrun;
import android.app.Activity;
import android.content.Context;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends Activity {
private TextView msg = null;
private Button openWIFI = null;
private Button closeWIFI = null;
private Button selectState = null;
private WifiManager wifiManager = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.activity_main);
this.msg = (TextView) super.findViewById(R.id.mag);
this.openWIFI = (Button) super.findViewById(R.id.openWIFI);
this.closeWIFI = (Button) super.findViewById(R.id.closeWIFI);
this.selectState = (Button) super.findViewById(R.id.selectState);
this.wifiManager = (WifiManager)super.getSystemService(Context.WIFI_SERVICE);
this.openWIFI.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
MainActivity.this.wifiManager.setWifiEnabled(true);//启动WIFI
MainActivity.this.msg.setText("打开WIFI,状态:" + MainActivity.this.wifiManager.getWifiState());
}
});
this.closeWIFI.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
MainActivity.this.wifiManager.setWifiEnabled(false);//关闭WIFI
MainActivity.this.msg.setText("关闭WIFI,状态:" + MainActivity.this.wifiManager.getWifiState());
}
});
this.selectState.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
MainActivity.this.msg.setText("检查WIFI,状态:" + MainActivity.this.wifiManager.getWifiState());
}
});
}
}
配置权限:
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
1.3 小结
(1)Service是在后台运行的一种无界面的Activity程序;
(2)在Android系统之中提供了多种Service供用户使用;