Android组件通信——Service(二十七)

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供用户使用;

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

毛栗子201105

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值