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 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 安卓控件——定时广播案例 -> 正文阅读

[移动开发]安卓控件——定时广播案例

安卓控件——广播

其实在我们的安卓系统中有好多的地方都应用到了广播的部分:比如当我们手机电量很低的时候,手机就会发一个广播,告知用户,作出相应的操作。

1.项目布局:

7个button,俩text;

2.布局文件:

activity_main:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:outlineAmbientShadowColor="@android:color/holo_blue_bright">

    <Button
        android:id="@+id/button1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_above="@+id/button2"
        android:layout_alignLeft="@+id/button2"
        android:text="Handler方式定时发送广播" />

    <Button
        android:id="@+id/button5"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/textView1"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="176dp"
        android:text="取消发送广播" />

    <Button
        android:id="@+id/button7"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/button5"
        android:layout_alignLeft="@+id/button5"
        android:layout_marginBottom="46dp"
        android:text="AlarmManager方式定时发送广播  5秒后发送广播,只发送一次" />

    <Button
        android:id="@+id/button3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/button5"
        android:layout_below="@+id/button5"
        android:text="Handler方式定时服务" />

    <Button
        android:id="@+id/button4"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/button3"
        android:layout_below="@+id/button3"
        android:text="AlarmManager方式定时服务" />

    <Button
        android:id="@+id/button2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_above="@+id/button7"
        android:layout_alignLeft="@+id/button7"
        android:text="AlarmManager方式定时发送广播  每隔5秒重复发广播" />

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/button1"
        android:layout_alignParentTop="true"
        android:layout_marginTop="41dp"
        android:text="敌军还有5秒到达战场,碾碎他们" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/textView1"
        android:layout_alignParentTop="true"
        android:text="敌军还有5秒到达战场,碾碎他们" />

    <Button
        android:id="@+id/button6"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/button4"
        android:layout_below="@+id/button4"
        android:text="取消定时服务" />



</RelativeLayout>

3.服务类:

TimerService.java:

package com.example.broadcast;

import android.annotation.SuppressLint;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;

public class TimerService extends Service {
    private String TAG =TimerService.class.getSimpleName();
    String message;
    int count=1;
    public TimerService() {
    }
    @Override
//    创建后台进程
    public void onCreate(){
        super.onCreate();
//        super.onDestroy();
//        调用发送函数
         sentMassage();
    }
//    销毁后台进程
public void onDestroy(){
        super.onDestroy();
        count=1;
    Log.i(TAG,"进程销毁咯!!");
}
//发送创建后机制的发送消息函数
    @SuppressLint("WrongConstant")
    private void sentMassage() {
        Toast.makeText(getApplicationContext(),"创建一个后台任务",0).show();
        stopSelf();
    }
//    接收消息
    public String getMessage(){
        return message;
    }


    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
//        throw new UnsupportedOperationException("Not yet implemented");
        return null;
    }
}

4.服务工具类:

4.1 ServiceUtil.java:

package com.example.broadcast;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

import java.util.List;

public class ServiceUtil {
    private final static String ServiceName="com.example.broadcast.TimerService";
    @SuppressLint("LongLogTag")
    public static boolean isServiceRunning(Context context, String className){
        boolean isRunning=false;
        ActivityManager activityManager =(ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningServiceInfo>serviceInfos=activityManager.getRunningServices(50);
        if (null==serviceInfos||serviceInfos.size()<1){
            return false;

        }
        for (int i=0;i<serviceInfos.size();i++){
            if (serviceInfos.get(i).service.getClassName().contains(className)){
                isRunning=true;
                break;
            }
        }
        Log.i("ServiceUtil-AlarmManager", className + " isRunning =  " + isRunning);
        return isRunning;
};
    @SuppressLint("LongLogTag")
    public static void startAMService(Context context){
        Log.i("ServiceUtil-AlarmManager", "invokeTimerPOIService wac called.." );
        PendingIntent alarmSender =null;
        Intent startIntent=new Intent(context,TimerService.class);
        startIntent.setAction(ServiceName);
        try{
            alarmSender=PendingIntent.getService(context,0,startIntent,0);

        }catch (Exception e){
//            异常捕获
//            闹钟异常启动
            Log.i("ServiceUtil-AlarmManager", "failed to start " + e.toString());
        }
        @SuppressLint("ServiceCast") AlarmManager am =(AlarmManager) context.getSystemService(Activity.ACTIVITY_SERVICE);
        am.setInexactRepeating(AlarmManager.RTC_WAKEUP,System.currentTimeMillis(),5*1000,alarmSender);

    }
    @SuppressLint("LongLogTag")
    public static void  cancleAMServicer(Context context){
//        关闭闹钟服务
        Log.i("ServiceUtil-AlarmManager", "cancleAlarmManager to start ");
        Intent intent =new Intent(context,TimerService.class);
        intent.setAction(ServiceName);
        PendingIntent pendingIntent=PendingIntent.getService(context,0,intent,PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarm=(AlarmManager)context.getSystemService(Activity.ALARM_SERVICE);
alarm.cancel(pendingIntent);
    }
//    服务启动
    public static void startHandlerService(Context cxt){
        Intent intent=new Intent(cxt,TimerService.class);
        cxt.startService(intent);

    }
//    服务关闭
//    服务启动
public static void stopHandlerService(Context cxt){
    Intent intent=new Intent(cxt,TimerService.class);
    cxt.stopService(intent);

}
}


4.2 实现广播和接收机制的五个步骤:

  1. 创建Intent对象,设置其属性action,这个属性是接收广播数据的标志标识,只有注册了相同的action属性的广播接收器才可以接收到相同的数据。
  2. 编写广播信息内容,将需要播发的内容封装到Intent里面,通过Activity或者是Service继承父类的Context的setContext()方式将广播发送出去;
  3. 编写继承BroadcastRecevier的子类作为广播接收器,该对象是接收广播信息并对信息进行处理的组件,在子类中重写Onrecieve()方法。
  4. 配置文件中注册广播接收类
  5. 销毁广播接收器:Android系统在执行onReceive()方法的时候会启动一个程序计时器,到一定的时间,该进程就会被销毁(所以广播机制不适合传递大数据量的信息)

5.主类:

5.1 MainActivity.java:

package com.example.broadcast;

import androidx.appcompat.app.AppCompatActivity;

import android.annotation.SuppressLint;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    // private TimerService mTimerService;
    private final String MESSAGE = "message";
    private Context mContext;
    private TextView tv, tv2;
    private Button bt1, bt2, bt3, bt4, bt5, bt6,bt7;
    private final int Time = 5 * 1000;
    private boolean isHanderType = false;
    private static final String ACTION_NAME = "android.intent.action.alarm.timer";
    private static final String ACTION_NAME2 = "android.intent.action.handler.timer";
    private int countHandler = 1;// handler广播发送次数计数器
    private int countAlarm = 0;// alarm广播发送次数计数器
    Handler handler = new Handler();
    Runnable runnable = new Runnable() {
        @Override
//    设置广播发送
        public void run() {
            // TODO Auto-generated method stub
//设置发布延时
            handler.postDelayed(runnable, Time);

            Intent mIntent = new Intent(ACTION_NAME2);

            mIntent.putExtra(MESSAGE, "这是第" + countHandler + "次"
                    + "Handler发送的广播,  接下来是第" + countHandler + "次");

            sendBroadcast(mIntent);

        }
    };

    Runnable runnable2 = new Runnable() {
        @Override
        public void run() {
            // TODO Auto-generated method stub
            Intent intent = new Intent(mContext, TimerService.class);
            startService(intent);
            handler.postDelayed(runnable2, Time);

        }
    };

    private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            String message = intent.getStringExtra(MESSAGE);

            if (action.equals(ACTION_NAME)) {

                tv.setText("第" + countAlarm + "发送"
                        + "AlarmManager的Alarm广播,  接下来发送第" + countAlarm
                        + "次广播");

                tv2.setText("与handler广播不同,我们的alarm广播是首先执行一次后,就得等待5s后在执行,并且发送的时候只执行一次");
                // Toast.makeText(MainActivity.this, message+countAlarm,
                // 0).show();
                countAlarm++;
            } else if (action.equals(ACTION_NAME2)) {

                if (!TextUtils.isEmpty(message)) {
                    tv2.setText(message);
                }

                countHandler++;

            }

        }

    };

    // ServiceConnection conn = new ServiceConnection() {
    // @Override
    // public void onServiceDisconnected(ComponentName name) {
    //
    // }
    //
    // @Override
    // public void onServiceConnected(ComponentName name, IBinder service) {
    // // TODO Auto-generated method stub
    // mTimerService = ((TimerService.MsgBinder)service).getService();
    // tv.setText(mTimerService.getMessage());
    //
    //
    // }
    //
    //
    //
    //
    // };

    @Override
    protected void onResume() {
        // TODO Auto-generated method stub
        super.onResume();
//注册广播
        registerBoradcastReceiver();

    }

    @Override
// 注册控件,注册控件监听
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);
        mContext = MainActivity.this;
        tv = (TextView) findViewById(R.id.textView1);
        tv2 = (TextView) findViewById(R.id.textView2);
        bt1 = (Button) findViewById(R.id.button1);
        bt2 = (Button) findViewById(R.id.button2);

        bt3 = (Button) findViewById(R.id.button3);
        bt4 = (Button) findViewById(R.id.button4);
        bt5 = (Button) findViewById(R.id.button5);

        bt6 = (Button) findViewById(R.id.button6);

        bt7 = (Button) findViewById(R.id.button7);
        bt1.setOnClickListener(onClickListener);
        bt2.setOnClickListener(onClickListener);
        bt3.setOnClickListener(onClickListener);
        bt4.setOnClickListener(onClickListener);
        bt5.setOnClickListener(onClickListener);
        bt6.setOnClickListener(onClickListener);
        bt7.setOnClickListener(onClickListener);

    }

    View.OnClickListener onClickListener = new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            switch (v.getId()) {
                case R.id.button1:
                    sendTimerBoaadCastReceiver(true,-1);
                    bt1.setEnabled(false);
                    break;
                case R.id.button2:
                    sendTimerBoaadCastReceiver(false,2);
                    bt2.setEnabled(false);
                    break;
                case R.id.button3:
                    sendTimerService(true);
                    bt3.setEnabled(false);
                    break;
                case R.id.button4:
                    sendTimerService(false);
                    bt4.setEnabled(false);
                    break;
                case R.id.button5:
                    cancelAlLBR();
                    break;
                case R.id.button6:
                    cancelAlLService();
                    break;
                case R.id.button7:
                    sendTimerBoaadCastReceiver(false,1);
                    bt7.setEnabled(false);
                    break;

            }

        }
    };

//注册广播

    private void registerBoradcastReceiver() {

        IntentFilter myIntentFilter = new IntentFilter();
        myIntentFilter.addAction(ACTION_NAME);
        myIntentFilter.addAction(ACTION_NAME2);
        //注册广播

        registerReceiver(mBroadcastReceiver, myIntentFilter);

    }


    @SuppressLint("WrongConstant")
    private void sendTimerBoaadCastReceiver(boolean isHandler, int state) {
//    判断是哪一种广播方式
        if (isHandler) {
//       使用Handle方式
//       设定多久执行一次runnable

            handler.postDelayed(runnable, Time);

        } else {

            Intent mIntent = new Intent(ACTION_NAME);
            // 发送广播
            Toast.makeText(MainActivity.this, "发送广播,开始进攻", 0).show();

            sendBroadcast(mIntent);
//以alarmManager的方式发送广播

            PendingIntent pendIntent = PendingIntent.getBroadcast(mContext, 0,
                    mIntent, PendingIntent.FLAG_UPDATE_CURRENT);
//注册闹铃
            AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE);


            switch (state) {
                /**
                 * 5秒后发送广播,只发送一次 elapsedRealtime() and elapsedRealtimeNanos()
                 * 返回系统启动到现在的时间,包含设备深度休眠的时间。该时钟被保证是单调的,
                 * 即使CPU在省电模式下,该时间也会继续计时。该时钟可以被使用在当测量时间间隔可能跨越系统睡眠的时间段。
                 *
                 */
                case 1:

//   AlarmManager提供的方法: void set(int type, long
//  triggerAtTime,PendingIntent operation) 设置一个闹钟
                    long triggerAtTime = SystemClock.elapsedRealtime() + Time;
                    manager.set(AlarmManager.ELAPSED_REALTIME, triggerAtTime,
                            pendIntent);
                    break;
                case 2:
//设置间隔多少秒执行闹钟

                    manager.setInexactRepeating(
                            AlarmManager.ELAPSED_REALTIME_WAKEUP,
                            SystemClock.elapsedRealtime(), Time, pendIntent);
                    break;
                case 3:
                    break;
                case 4:
                    break;

            }

        }

    }

    //取消handler闹钟
    private void cancelHandlerBR() {

        handler.removeCallbacks(runnable);
        countHandler = 1;
        tv2.setText("敌军还有5s到达,击垮他们");

    }
    //取消AlarmManager闹钟
    private void cancelAlarmManagerBR() {
        Intent mIntent = new Intent(ACTION_NAME);

        PendingIntent pendIntent = PendingIntent.getBroadcast(mContext, 0,
                mIntent, 0);

        AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE);
        manager.cancel(pendIntent);

        countAlarm = 0;
//    改变text控件内容

        tv.setText("敌军还有5s到达,击垮他们");
    }
// 取消广播服务

    private void cancelAlLBR() {

        cancelHandlerBR();
        cancelAlarmManagerBR();
        bt1.setEnabled(true);
        bt2.setEnabled(true);
        bt7.setEnabled(true);

    }

    private void cancelAlLService() {
        handler.removeCallbacks(runnable2);
        ServiceUtil.cancleAMServicer(mContext);
        ServiceUtil.stopHandlerService(mContext);
//让按钮可以点击
        bt3.setEnabled(true);
        bt4.setEnabled(true);
        bt6.setEnabled(true);
        //    改变text控件内容


        tv2.setText("敌军还有5s到达,击垮他们");
        tv.setText("敌军还有5s到达,击垮他们");

    }

    //发送定时服务
    private void sendTimerService(boolean isHandler) {

        if (isHandler) {
            handler.postDelayed(runnable2, Time);

        } else {
            ServiceUtil.startAMService(mContext);

        }

    }
// 销毁进程

    @Override
    protected void onDestroy() {
        // TODO Auto-generated method stub
        super.onDestroy();
        cancelAlLBR();
        cancelAlLService();
        // unbindService(conn);
        unregisterReceiver(mBroadcastReceiver);
    }

    @Override
    protected void onPause() {
        // TODO Auto-generated method stub
        super.onPause();

    }

}

5.2 对比

注意handler和alarmManager有一些不同, 首先我们给两种方式定义一个计数器:

  1. handler广播发送次数计数器:
private int countHandler = 1;
  1. alarm广播发送次数计数器
private int countAlarm = 0;

注意:与handler广播不同,我们的alarm广播是首先执行一次后,就得等待5s后在执行,并且发送的时候只执行一次

5.3 按钮触发

注意我們也需要设置在正在执行广播的时候,我们的按钮出处于的状态(能否被点击)

  1. 取消广播的时候:

相应的三个广播按钮就是可以用了。

//  取消广播服务

    private void cancelAlLBR() {

        cancelHandlerBR();
        cancelAlarmManagerBR();
        bt1.setEnabled(true);
        bt2.setEnabled(true);
        bt7.setEnabled(true);

    }
  1. 取消所有的服务的时候:

这个时候相应的三个启动按钮还是可以用的

//取消所有的服務
    private void cancelAlLService() {
        handler.removeCallbacks(runnable2);
        ServiceUtil.cancleAMServicer(mContext);
        ServiceUtil.stopHandlerService(mContext);
//让按钮可以点击
        bt3.setEnabled(true);
        bt4.setEnabled(true);
        bt6.setEnabled(true);
        //    改变text控件内容


        tv2.setText("敌军还有5s到达,击垮他们");
        tv.setText("敌军还有5s到达,击垮他们");

    }

6. 项目文件配置:

AndroidManifest.xml

这个地方请注意,如果是你在新建服务的时候选择的是新建服务,那么就会自动在这个配置文件里面自动注册,但是如果你直接新建的java文件,也没关系,但是你需要自己在这个地方进行相关的配置。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.broadcast">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <service
            android:name=".TimerService"
            android:enabled="true"
            android:exported="true"></service>

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

7. 成果展示:

image-20211210115837807

image-20211210115900751

image-20211210115929291

8.提取几个重要片段:

看完我们整个代码流程,梳理一下,我们在服务工具类文件里设置action属性,再在项目启动主文件里设置注册广播以及处理onClick按钮点击事件的处理,启动后台服务,将intent传值给后台服务,TimerService服务类就启动服务,发送广播,根据广播信息更改文本。在到服务工具类启动后台任务,换新闹钟服务

8.1 ServiceUtil.java:设置action属性

Intent startIntent=new Intent(context,TimerService.class);
startIntent.setAction(ServiceName);

8.3 MainActivity.java:注册广播


//注册广播

registerReceiver(mBroadcastReceiver, myIntentFilter);

8.4 MainActivity.java:按钮点击事件的处理

View.OnClickListener onClickListener = new View.OnClickListener() {

    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        switch (v.getId()) {
            case R.id.button1:
                sendTimerBoaadCastReceiver(true,-1);
                bt1.setEnabled(false);
                break;
            case R.id.button2:
                sendTimerBoaadCastReceiver(false,2);
                bt2.setEnabled(false);
                break;
            case R.id.button3:
                sendTimerService(true);
                bt3.setEnabled(false);
                break;
            case R.id.button4:
                sendTimerService(false);
                bt4.setEnabled(false);
                break;
            case R.id.button5:
                cancelAlLBR();
                break;
            case R.id.button6:
                cancelAlLService();
                break;
            case R.id.button7:
                sendTimerBoaadCastReceiver(false,1);
                bt7.setEnabled(false);
                break;

        }

    }
};

我觉得这个部分还是不简单地,大家有什么问题希望及时留言嗷,私信都可以!

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-12-11 15:50:25  更:2021-12-11 15:52:05 
 
开发: 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年11日历 -2024/11/24 7:38:26-

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