广播和IntentService

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);
    }
}

融合Service、广播、handler、AlarmManager等知识点实现一个闹钟

实现思路  开启Service后传过去当前时间,并累加时间,通过binder通信更新时间,利用AlarmManager设置定时任务,当时间到后发广播提醒用户。

 ClockActivity中的核心代码

    private ServiceConnection conn = new ServiceConnection() {

        //Activity与Service断开连接时回调该方法
        @Override
        public void onServiceDisconnected(ComponentName name) {
            System.out.println("------Service DisConnected-------");
        }
        //Activity与Service连接成功时回调该方法
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            System.out.println("------Service Connected-------");
            binder = (ClockService.MyBinder) service;
            System.out.println(binder.getTime());
        }
    };

 ClockActivity中onCreate中的代码,需要注意的是bindService是异步的,在onResume执行之后才会执行,因此如果在onCreate中想要获取binder会获得到null

             //启动计时服务
        Intent intent = new Intent(ClockActivity.this, ClockService.class);
        intent.putExtra("time",""+Calendar.getInstance().getTimeInMillis());
        startService(intent);
        bindService(intent, conn, Service.BIND_ABOVE_CLIENT);


     //实现闹钟模块的代码
        currentTimeText = findViewById(R.id.time_text);
        clockText = findViewById(R.id.clock_text);
        Button clockButton = findViewById(R.id.button_clock);
        //设置当前时间
        currentTimeText.setText(time);

        alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);


        //注册广播主要用来刷新时间
        IntentFilter clockIntentFilter = new IntentFilter();
        clockIntentFilter.addAction(CLOCK_ACTION);
        registerReceiver(clockReceiver,clockIntentFilter);

        Intent receiverIntent = new Intent();
        receiverIntent.setAction(CLOCK_ACTION);
        PendingIntent pi = PendingIntent.getBroadcast(ClockActivity.this,0,receiverIntent,PendingIntent.FLAG_UPDATE_CURRENT);

        clockButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Calendar currentTime = Calendar.getInstance();
                new TimePickerDialog(ClockActivity.this, 0,
                        new TimePickerDialog.OnTimeSetListener() {
                            @Override
                            public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
                                //设置当前时间
                                Calendar c = Calendar.getInstance();
                                c.setTimeInMillis(System.currentTimeMillis());
                                // 根据用户选择的时间来设置Calendar对象
                                c.set(Calendar.HOUR, hourOfDay);
                                c.set(Calendar.MINUTE, minute);

                                SimpleDateFormat sdf=new SimpleDateFormat("HH:mm:ss");
                                String sd = sdf.format(new Date(c.getTimeInMillis()));
                                clockText.setText(sd);

                                // 设置AlarmManager在Calendar对应的时间启动Activity
                                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

                                    alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(), pi);
                                }
                                Log.e("HEHE",c.getTimeInMillis()+"");   //这里的时间是一个unix时间戳
                                // 提示闹钟设置完毕:
                                Toast.makeText(ClockActivity.this, "闹钟设置完毕~"+ c.getTimeInMillis(),
                                        Toast.LENGTH_SHORT).show();
                            }
                        }, currentTime.get(Calendar.HOUR_OF_DAY), currentTime
                        .get(Calendar.MINUTE), false).show();
                
            }
        });

        new Timer().schedule(new TimerTask() {
            @Override
            public void run() {
                if(binder!=null){
                    // 创建消息
                    Message msg = new Message();
                    msg.what = 0x123;
                    Bundle bundle = new Bundle();
                    bundle.putString("current_time",binder.getTime());
                    msg.setData(bundle);
                    myHandler.sendMessage(msg);
                }
            }
        },0,1000);

ClockService 主要用于实现时间戳累加任务 

public class ClockService extends Service {
    public final static String mServiceAction = "com.example.myproject.mServiceAction";

    private Thread mClockThread;
    private  boolean controllerFlag = false;
    public static long TIME = 0;
    public   static boolean clockFlag = true;
    public ClockService() {
    }

    //定义onBinder方法所返回的对象
    private MyBinder binder = new MyBinder();
    public class MyBinder extends Binder
    {
        public String getTime(){
            SimpleDateFormat sdf=new SimpleDateFormat("HH:mm:ss");
            String sd = sdf.format(new Date(TIME));
            return sd;
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(mServiceAction);
        registerReceiver(serverController,intentFilter);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);

    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        TIME = Long.parseLong(intent.getStringExtra("time"));
        mClockThread = new Thread(new Runnable() {
            @Override
            public void run() {
                while(clockFlag){
                    try {
                        Thread.sleep(1000);
                        TIME += 1000;
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        mClockThread.start();

        return binder;
    }

    //Service断开连接时回调
    @Override
    public boolean onUnbind(Intent intent) {

        return true;
    }


    //Service被关闭前回调
    @Override
    public void onDestroy() {
        clockFlag = false;
        super.onDestroy();
    }

    @Override
    public void onRebind(Intent intent) {
        super.onRebind(intent);
    }


}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值