前言:
我们都知道Android的四大基本组件:Activity、ContentProvider、Service以及BroadcastReceiver,前面的两个我们在前几篇已经具体讲解了,今天这一天我们就把后两者的使用具体说一下,由于Service和BroadcastReceiver常常一起使用,所以我们一起来学习。
一.Service的使用
Service是Android系统的后台服务组件,没有用户界面,但可以长时间的运行,比Activity的优先级高,可以用于进程间的通信。
Service也同Activity一样有自己的生命周期,但是Service有两种生命周期,也就是Service由两种启动以及对应的停止方式:
1.以启动方式使用的Service:
(1)特点:
A.通过Content.startService()启动,Content.stopService()或者Content.stopSelf()来停止;
(即只能通过其他组件启动,但可以自己停止)
B.不能与外部的组件进行交互;
(2)生命周期:
onCreate——>onStartCommand——>onDestroy
(3)示例代码:L0828_Service(记得注册)
MyService.java:
package com.example.l0828_service; import java.util.Timer; import java.util.TimerTask; import android.app.Service; import android.content.Intent; import android.os.IBinder; public class MyService extends Service{ //声明定时器,用于创建新的进程来计时 private Timer timer; private TimerTask task; private static int i=0; //继承Service必须要重写的方法onBind @Override public IBinder onBind(Intent intent) { return null; } /*Service的生命周期一:onCreate、onStartCommand、onDestroy方法构成*/ //onCreate方法,启动服务,每次启动仅仅调用一次 @Override public void onCreate() { System.out.println("onCreate"); super.onCreate(); } //onStartCommand方法,一般在其中完成Service的工作 @Override public int onStartCommand(Intent intent, int flags, int startId) { System.out.println("onStartCommond"); startTimer(); return super.onStartCommand(intent, flags, startId); } //onDestroy方法,用来释放Service的资源 @Override public void onDestroy() { System.out.println("onDestroy"); stopTimer(); super.onDestroy(); } //开启定时器 public void startTimer(){ timer =new Timer(); task=new TimerTask(){ @Override public void run() { i++; System.out.println(i); } }; timer.schedule(task, 1000, 1000); } //停止定时器 public void stopTimer(){ timer.cancel(); } }
Mainactivity.java:
package com.example.l0828_service; 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 MainActivity extends Activity implements OnClickListener{ private Button btn_start,btn_stop; //声明Intent用于Activity向Service的跳转 private Intent intent; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn_start=(Button) findViewById(R.id.btn_start); btn_stop=(Button) findViewById(R.id.btn_stop); btn_start.setOnClickListener(this); btn_stop.setOnClickListener(this); //Activity组件向Service组件的跳转 intent=new Intent(MainActivity.this,MyService.class); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_start: //开启服务 startService(intent); break; case R.id.btn_stop: //停止服务 stopService(intent); break; } } }
主配置文件.xml文件中注册:
<service android:name="MyService"></service>
运行效果:
起始界面
点击开始——停止的过程显示:
停止之后再次点击开始按钮又重新执行onCreate方法:
2.以绑定方式使用的Service:
(1)特点:
A.通过Content.bindService()绑定而建立与服务器的连接,通过Content.unbindService()方法解除绑定从而断开与服务器的连接;
B.如果没有调用startService直接通过调用bindService绑定服务器也会自动启动服务器;
C.能获得Service的对象,从而能够使得其他组件与Service的交互;
D.同一个Service可以绑定多个服务连接,同时与不同的组件交互;
(2)生命周期:
onCreate——>onBind——>onCommand——>onUnbind——>onRebind——>onDestroy
如果onUnbind方法返回true,则当取消绑定之后重写绑定服务时就直接调用onRebind方法了。
(3)示例代码:
MyService.java:
package com.example.l0828_service2; import java.util.Timer; import java.util.TimerTask; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.IBinder; public class MyService extends Service{ private Timer timer; private TimerTask task; private int i=0; private int j=0; //创建内部类,用于创建Binder对象,onBinder方法中使用 class MyBinder extends Binder{ public MyService getService(){ return MyService.this; } } private MyBinder binder=new MyBinder(); public int getI() { return i; } public void setI(int i) { this.i = i; } public int getJ() { return j; } public void setJ(int j) { this.j = j; } //下面分别重写Service生命周期的方法 @Override public IBinder onBind(Intent intent) { //绑定服务,开始于界面交互 startTimer(); System.out.println("onBind"); return binder; } @Override public void onCreate() { System.out.println("onCreate"); super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { System.out.println("onStartCommand"); return super.onStartCommand(intent, flags, startId); } @Override public boolean onUnbind(Intent intent) { //解除与服务器的绑定,停止与界面的交互 stopTimer(); System.out.println("onUnbind"); //为了使onRebind能够调用到,使得onUnbind的返回值为true super.onDestroy(); return true; } @Override public void onRebind(Intent intent) { System.out.println("onRebind"); super.onRebind(intent); } @Override public void onDestroy() { System.out.println("onDestroy"); } //创建定时器,即创建另一个线程负责计时 public void startTimer(){ timer=new Timer(); task=new TimerTask() { @Override public void run() { i++; if(i==j){ System.out.println("此时您输入的数据于服务数据相同:"+j); } System.out.println(i); } }; timer.schedule(task, 1000,1000); } //停止计时 public void stopTimer(){ timer.cancel(); } }
MainActivity.java:
package com.example.l0828_service2; import com.example.l0828_service2.MyService.MyBinder; 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.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; public class MainActivity extends Activity implements OnClickListener,ServiceConnection{ private Button btn_bind,btn_unBind,btn_getService,btn_start,btn_stop; private Intent intent; private MyService myservice; private EditText et; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); et=(EditText) findViewById(R.id.et); btn_bind=(Button) findViewById(R.id.btn_bind); btn_unBind=(Button) findViewById(R.id.btn_unBind); btn_getService=(Button) findViewById(R.id.btn_getService); btn_start=(Button) findViewById(R.id.btn_start); btn_stop=(Button) findViewById(R.id.btn_stop); btn_bind.setOnClickListener(this); btn_unBind.setOnClickListener(this); btn_getService.setOnClickListener(this); btn_start.setOnClickListener(this); btn_stop.setOnClickListener(this); intent=new Intent(MainActivity.this, MyService.class); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_bind: bindService(intent, this, BIND_AUTO_CREATE); break; case R.id.btn_unBind: unbindService(this); break; case R.id.btn_getService: String info=et.getText().toString(); if("".equals(info)){ Toast.makeText(MainActivity.this,"当前的i值:"+myservice.getI() , Toast.LENGTH_SHORT).show(); } myservice.setJ(Integer.parseInt(info)); break; case R.id.btn_start: startService(intent); break; case R.id.btn_stop: stopService(intent); break; } } @Override public void onServiceConnected(ComponentName name, IBinder service) { MyService.MyBinder binder=(MyBinder) service; myservice=binder.getService(); } @Override public void onServiceDisconnected(ComponentName name) { } }
运行效果:
初始界面:
依次点击start、bind、unbind、输入一个服务还未计时到的数、getService、stop的过程:
下图是上面执行过程的输出情况,可以清晰明了的看出整个执行的过程:
下面是这样的执行顺序的结果:
start、bind、输入及时数据、getService、unbind、(正是此时调用了onRebind方法)bind、unbind、stop的过程
二.BroadcastReceiver的使用
1.使用广播实现简单的数据接收功能:
(1)MainActivity.java:
package com.example.l0829_broadcastreceiver; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.btn_send).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //仍然是使用Intent来实现组件之间的跳转 Intent intent=new Intent(MainActivity.this, MyBroadCastReceiver.class); //把要向广播接收器发送的数据用Intent对象封装,注意键值要相同 intent.putExtra("name", "我接收到了"); //发送数据 sendBroadcast(intent); } }); } }
(2)MyBroadcastReceiver.java:
package com.example.l0829_broadcastreceiver; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; //继承BroadcastReceiver public class MyBroadCastReceiver extends BroadcastReceiver{ //只需重写OnReceiver方法 @Override public void onReceive(Context context, Intent intent) { //接收特定键值的数据,实现广播接收器的基本功能 String str=intent.getStringExtra("name"); System.out.println(str); } }
(3)一定不要忘记注册啊(四大基本组件是都需要在主配置文件中注册的):
<receiver android:name="MyBroadCastReceiver"></receiver>
2.再实现一个系统默认广播的例子——电量改变的广播:
(1)MainActivity.java
package com.example.l0829_system_broadcastreceiver; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.widget.TextView; public class MainActivity extends Activity { //创建一个广播的实例,在其onReceive方法中实现接收的过程 private BroadcastReceiver myBR=new BroadcastReceiver(){ @Override public void onReceive(Context context, Intent intent) { //if(Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction()))这里也可以先判断一下,确保正确性 //下面就是接收系统当前电量信息的过程,注意这里的键值level和scale是系统固定值,不能改变 int level=intent.getIntExtra("level", 0); int scale=intent.getIntExtra("scale", 100); tv.setText("当前电量:"+level*100/scale+"%"); } }; //声明一个TextView用来显示接受的当前电量值 private TextView tv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv=(TextView) findViewById(R.id.tv_receive); //动态注册广播的方法,在onCreate方法中 registerReceiver(myBR, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); } @Override protected void onStop() { //在onStop方法中取消广播的注册 unregisterReceiver(myBR); super.onStop(); } }
(2)由于在代码中实现了Receiver的动态注册,那么主配置文件中就不用注册了
(3)运行效果:(有点小哈,凑合看看吧)
(另外有一个温馨提示:模拟器的电量值永远是50%,可以用真机测试)
3.最后算是来个总结吧:
我们实现一个Activity、Service、BroadcastReceiver三大组件结合使用的例子,完成Service始终在后台计时、BroadcastReceiver接收数据并及时更新主Activity的过程:
(1)MyService.java
package com.example.l0829_zujian_all; import java.util.Timer; import java.util.TimerTask; import android.app.Service; import android.content.Intent; import android.os.IBinder; public class MyService extends Service{ private Timer timer; private TimerTask task; private int i=0; private Intent intent; public int getI() { return i; } public void setI(int i) { this.i = i; } @Override public void onCreate() { //开始服务 startTimer(); super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { return super.onStartCommand(intent, flags, startId); } @Override public IBinder onBind(Intent intent) { return null; } @Override public boolean onUnbind(Intent intent) { return super.onUnbind(intent); } @Override public void onRebind(Intent intent) { super.onRebind(intent); } @Override public void onDestroy() { //停止服务 stopTimer(); super.onDestroy(); } public void startTimer(){ timer=new Timer(); task=new TimerTask() { @Override public void run() { i++; //在计时器中及时向ACTION_MY的BroadcastReceiver接收器中发送键值为id的数据 intent=new Intent(); intent.setAction("ACTION_MY"); intent.putExtra("id", i); sendBroadcast(intent); } }; timer.schedule(task, 500,1000); } public void stopTimer(){ timer.cancel(); } }
(2)MainActivity.java
package com.example.l0829_zujian_all; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; 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 implements OnClickListener{ //创建接收器对象,并在onReceive方法中接收键值为id的数据 private BroadcastReceiver br=new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { int val=intent.getIntExtra("id", 0); System.out.println(intent.getIntExtra("id", 0)); tv_show.setText(val+""); } }; private Button btn_start,btn_stop; private TextView tv_show; private Intent intent; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv_show=(TextView) findViewById(R.id.tv_show); btn_start=(Button) findViewById(R.id.btn_start); btn_stop=(Button) findViewById(R.id.btn_stop); btn_start.setOnClickListener(this); btn_stop.setOnClickListener(this); intent=new Intent(MainActivity.this, MyService.class); //接收器的动态注册,Action必须与Service中的Action一致 registerReceiver(br, new IntentFilter("ACTION_MY")); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_start: startService(intent); break; case R.id.btn_stop: stopService(intent); break; } } @Override protected void onDestroy() { //取接收器的消注册 unregisterReceiver(br); super.onDestroy(); } }
(3)注册Service,而BroadcastReceiver就不用再注册了
(4)运行效果:
即一个计时更新主页面的功能