IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 广播和IntentService -> 正文阅读

[移动开发]广播和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);
    }
}

?

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-08-01 14:37:31  更:2021-08-01 14:39:53 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/20 3:53:42-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码