1 动态注册和静态注册
静态注册和动态注册的区别:
① 动态注册是在Java类中注册,而静态注册是在AndroidManifest.xml中注册。
②?动态注册的广播接收器不是常驻型的,会随着所注册的Activity的结束而结束,如果所在的Activity已经destroy了,那么该广播接收器也就不能再继续接收广播了。注意:在Activity结束前,要取消注册广播接收器,不然会导致内存泄露;静态注册的广播接收器是常驻型的,即使所在的APP被关闭了,也是可以接收到广播的。
?1)动态注册监听网络变化
利用一个网络状态监听器来说明,建立一个继承BroadcastReceiver的广播接收器,通过监听?intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");//网络发生变化时系统发出android.net.conn.CONNECTIVITY_CHANGE的广播,当网络发生变化时,onReceive()方法得到执行。需要注意的是?要在AndroidManifest.xml中?加入权限配置。
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
public class FifthActivity extends AppCompatActivity {
private final static String TAG = "XULIWEI_ACTIVITY";
private IntentFilter intentFilter;
private NetworkChangeReceiver networkChangeReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fifth);
Button button = findViewById(R.id.button_3);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(FifthActivity.this,MainActivity.class);
// intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
// intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
}
});
Log.d(TAG,"FifthActivity onCreate "+this.toString());
intentFilter = new IntentFilter();
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");//网络发生变化时系统发出android.net.conn.CONNECTIVITY_CHANGE的广播
networkChangeReceiver = new NetworkChangeReceiver();
registerReceiver(networkChangeReceiver,intentFilter);
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(TAG,"FifthActivity onDestroy "+this.toString());
unregisterReceiver(networkChangeReceiver);
}
//通过广播接收器监听网络变化
class NetworkChangeReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
// Toast.makeText(context,"network changes",Toast.LENGTH_LONG).show();
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);//ConnectivityManager是一个系统服务类,专门用来管理网络连接的
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
if(networkInfo!=null&&networkInfo.isAvailable()){
Toast.makeText(context,"网络正常",Toast.LENGTH_LONG).show();
}else{
Toast.makeText(context,"无网络",Toast.LENGTH_LONG).show();
}
}
}
}
2)静态注册实现开机自启?
利用静态注册实现开机自启提示,静态注册可以不依赖与某一个应用
广播接收器
public class BootCompleteReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
// an Intent broadcast.
Toast.makeText(context,"开机了",Toast.LENGTH_LONG).show();
}
}
在AndroidManifest.xml中注册,并且要添加权限
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<receiver
android:name=".broadcasttest.BootCompleteReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
2.IntentService
IntentService 与普通Service的区别是,
(1) Service不是独立的进程,也不是独立的线程,它是依赖于应用程序的主线程的,不建议在Service中编写耗时的逻辑和操作,否则会引起ANR。
(2) IntentService 它创建了一个独立的工作线程来处理所有的通过onStartCommand()传递给服务的intents(把intent插入到工作队列中)。通过工作队列把intent逐个发送给onHandleIntent()。
(3) 不需要主动调用stopSelft()来结束服务。因为,在所有的intent被处理完后,系统会自动关闭服务。
下图是IntentService的生命周期,可以看到IntentService与活动主线程不是一个,在服务处理结束后会自动关闭服务
IntentService通过广播与Activity通信
广播地址
public static String SERVICE_RECEIVER = "com.example.myproject.broadcasttest.MsgReceiver";
AndroidManifest.xml注册
<receiver
android:name=".broadcasttest.MsgReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.example.myproject.broadcasttest.MsgReceiver" />
</intent-filter>
</receiver>
活动页面按钮点击后启动IntentService 服务 ,并注册广播接收器
Button intentServiceButtion = findViewById(R.id.btn_intent_service);
intentServiceButtion.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d(TAG,"Thread id is "+Thread.currentThread().getId());
//动态注册广播接收器
Toast.makeText(getApplicationContext(), "Service的count的值为:", Toast.LENGTH_SHORT).show();
msgReceiver = new MsgReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(SERVICE_RECEIVER);
registerReceiver(msgReceiver,intentFilter);
//启动后台服务
Intent intent = new Intent(SecondActivity.this, MyIntentService.class);
startService(intent);
}
});
}
IntentService模拟完成任务后,广播通知广播接收器
public class MyIntentService extends IntentService {
private final String TAG = "XULIWEI_SERVICE";
public MyIntentService() {
super("MyIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
//打印当前进程的id
Log.d(TAG, "开始完成任务,通过进程"+Thread.currentThread().getId());
//发送广播通知到Activity
Intent sendIntent = new Intent(SecondActivity.SERVICE_RECEIVER);
intent.setPackage("com.example.myproject.broadcasttest");
sendIntent.putExtra("progressID",Thread.currentThread().getId());
sendBroadcast(intent);
Log.d(TAG, "广播,通过进程"+Thread.currentThread().getId());
}
@Override
public void onDestroy() {
// super.onDestroy();
Log.d(TAG,"intentService onDestroy");
}
}
通过广播接收器提示intentService服务已完成
//通过广播接收器提示intentService服务已完成
public class MsgReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String progressID = intent.getStringExtra("progressID");
Log.d(SecondActivity.TAG,"进程"+progressID+"下的服务处理已完成");
}
}
结合Service和广播实现计时器
?
思路:启动一个Service,创建一个线程用于计时,在Service和Activity两边分别添加一个广播接收器,当点击开始时,通知服务开始计时,服务端每隔1秒发送一个广播到Activity,刷新页面,显示最新的时间,当点击结束,Activity端发送广播停止计时。
package com.example.mybroadreceiver;
import androidx.appcompat.app.AppCompatActivity;
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.widget.Button;
import android.widget.TextView;
public class ClockActivity extends AppCompatActivity {
private TextView tvClock;
public static final String CLOCK_ACTION="com.jereh.Clock_Action";
public static int TIME=2*60*60*1000;//倒计时2个小时
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_clock);
tvClock=findViewById(R.id.tvClock);
regReceiver();//注册广播
startService(new Intent(this,ClockService.class));//启动计时服务
Button clockStartButtion = findViewById(R.id.button_clock_start);
//通过发送广播,控制计时服务
//继续计时
clockStartButtion.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent();
intent.setAction(ClockService.CLOCK_SERVICE_ACTION);
intent.putExtra("method", "continue");
sendBroadcast(intent);
}
});
//通过发送广播,控制计时服务
//暂停计时
Button clockEndButtion = findViewById(R.id.button_clock_end);
clockEndButtion.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent=new Intent();
intent.setAction(ClockService.CLOCK_SERVICE_ACTION);
intent.putExtra("method","pause");
sendBroadcast(intent);
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
super.unregisterReceiver(clockReceiver);
TIME=2*60*60*1000;
Intent intent=new Intent();
intent.setAction(ClockService.CLOCK_SERVICE_ACTION);
intent.putExtra("method", "stop");
super.sendBroadcast(intent);
}
private void regReceiver(){
IntentFilter intentFilter=new IntentFilter();
intentFilter.addAction(CLOCK_ACTION);
super.registerReceiver(clockReceiver, intentFilter);
}
/**
*广播接受者,接受来自ClockService(计时服务)的广播,ClockService每隔一秒
*钟发一次广播
*/
private BroadcastReceiver clockReceiver=new BroadcastReceiver(){
@Override
public void onReceive(Context context, Intent intent) {
changeTime();//改变TextView中的显示时间
}
};
private void changeTime(){
String stime="";
if(TIME==0){
stime="计时结束";
}else{
int hour=TIME/(1000*60*60);
int minute=TIME%(1000*60*60)/(60*1000);
int second=(TIME%(1000*60*60))%(60*1000)/1000;
String shour=""+hour,sminute=""+minute,ssecond=""+second;
if(hour<=9){
shour="0"+hour;
}
if(minute<=9){
sminute="0"+minute;
}
if (second<=9){
ssecond="0"+second;
}
stime=shour+":"+sminute+":"+ssecond;
}
tvClock.setText(stime);
}
}
package com.example.mybroadreceiver;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
public class ClockService extends Service {
public static final String CLOCK_SERVICE_ACTION="clock_service_actoin";
private boolean controllOpt=true;
public ClockService() { }
@Override
public void onCreate(){
IntentFilter intentFilter=new IntentFilter();
intentFilter.addAction(CLOCK_SERVICE_ACTION);
//在service中注册广播(serviceController),接受来自ClockActivity中
//的广播信息,实现对计时服务的控制(暂停、继续)
super.registerReceiver(serviceController,intentFilter);
}
@Override
public int onStartCommand(Intent intent,int flags,int startId){
countTime();//执行计时功能
return Service.START_STICKY;
}
//实现计时功能,每隔一秒减少总时间并ClockActivity发送广播
private void countTime(){
new Thread(new Runnable() {
@Override
public void run() {
Intent intent= new Intent(ClockActivity.CLOCK_ACTION);
while(controllOpt){
try {
Thread.sleep(1000);
if(ClockActivity.TIME<=0){
sendBroadcast(intent);
stopSelf();
break;
}
ClockActivity.TIME-=1000;
sendBroadcast(intent);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
//广播接受者,接受来自ClockActivity的广播以便暂停、继续、停止广播
private BroadcastReceiver serviceController=new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String method=intent.getStringExtra("method");
switch (method){
case "pause":
controllOpt=false;
break;
case "continue":
controllOpt=true;
countTime();
break;
case "stop":
controllOpt=false;
stopSelf();
break;
}
}
};
@Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public void onDestroy(){
super.unregisterReceiver(serviceController);
}
}
?
|