广播

1.什么是广播        

2.标准广播

BroadStandardActivity.java

package com.tiger.chapter09;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;

import com.tiger.chapter09.receiver.StandardReceiver;

public class BroadStandardActivity extends AppCompatActivity implements View.OnClickListener {

    private StandardReceiver standardReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_broad_standard);
        findViewById(R.id.btn_send_standard).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        //发送标准广播  相当于主题
        Intent intent = new Intent(StandardReceiver.STRING);



        sendBroadcast(intent);
    }


    @Override
    protected void onStart() {
        super.onStart();
        standardReceiver = new StandardReceiver();
        //代表上下文 注册 广播接收者  相当于订阅
        IntentFilter intentFilter = new IntentFilter(StandardReceiver.STRING);
        //注册接收器,注册之后才能正常接收广播
        registerReceiver(standardReceiver,intentFilter);
    }

    @Override
    protected void onStop() {
        super.onStop();
        //在Activity不用的时候就不需要 广播订阅了,先注销接收者
        unregisterReceiver(standardReceiver);


    }
}

xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="5dp">

    <Button
        android:id="@+id/btn_send_standard"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="发送标准广播"
        android:textColor="@color/black"
        android:textSize="17sp" />

</LinearLayout>

receiver

package com.tiger.chapter09.receiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

//定义一个标准广播的接收器
public class StandardReceiver extends BroadcastReceiver {

    public static final String STRING ="com.tiger.chapter09.standard";
    //一旦接收到标准广播,马上触发接收器的onReceive方法
    @Override
    public void onReceive(Context context, Intent intent) {
        //先当于订阅主题
        if (intent!=null&&intent.getAction().equals(STRING)){
            Log.d("ning","收到了标准广播");
        }
    }
}

3.有序广播

 BroadOrderActivity.java

package com.tiger.chapter09;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;

import com.tiger.chapter09.receiver.OrderAReceiver;
import com.tiger.chapter09.receiver.OrderBReceiver;

public class BroadOrderActivity extends AppCompatActivity implements View.OnClickListener {

    public static final String ORDER_ACTION = "com.tiger.chapter09.order";
    private OrderAReceiver orderAReceiver;
    private OrderBReceiver orderBReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_broad_order);
        findViewById(R.id.btn_send_order).setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
        //创建一个指定动作的意图
        Intent intent  =new Intent(ORDER_ACTION);
        //发送有序广播
        sendOrderedBroadcast(intent,null);
    }

    @Override
    protected void onStart() {
        super.onStart();
        //多个接收器处理有序广播的顺序规则为:
        //1.优先级越大的2接收器,越早收到有序广播
        //2.优先级相同的时候,越早注册的接收器越早收到有序广播
        orderAReceiver = new OrderAReceiver();
        IntentFilter filterA = new IntentFilter(ORDER_ACTION);
        filterA.setPriority(8);
        registerReceiver(orderAReceiver,filterA);

        orderBReceiver = new OrderBReceiver();
        IntentFilter filterB = new IntentFilter(ORDER_ACTION);
        filterB.setPriority(10);
        registerReceiver(orderBReceiver,filterB);


    }

    @Override
    protected void onStop() {
        super.onStop();
        unregisterReceiver(orderAReceiver);
        unregisterReceiver(orderBReceiver);
    }
}

AOrder

package com.tiger.chapter09.receiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

import com.tiger.chapter09.BroadOrderActivity;

public class OrderAReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent!=null&&intent.getAction().equals(BroadOrderActivity.ORDER_ACTION)){
            Log.d("ning","接收器A 收到了有序广播");
        }


    }
}

BOrder

package com.tiger.chapter09.receiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

import com.tiger.chapter09.BroadOrderActivity;

public class OrderBReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent!=null&&intent.getAction().equals(BroadOrderActivity.ORDER_ACTION)){
            Log.d("ning","接收器B 收到了有序广播");
            abortBroadcast();//中断广播,此时后面的接收器无法收到该广播
        }


    }
}

4.广播的静态注册

activity

package com.tiger.chapter09;

import androidx.appcompat.app.AppCompatActivity;

import android.content.ComponentName;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;

import com.tiger.chapter09.receiver.ShockReceiver;

public class BroadStaticActivity extends AppCompatActivity implements View.OnClickListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_broad_static);
        findViewById(R.id.btn_send_shock).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        //Android8.0 之后 删除了大部分静态注册,防止退出App后仍在接收广播
        //为了让应用能够继续接收静态广播,需要给静态注册的广播指定包名

        String fullName = "com.tiger.chapter09.receiver.ShockReceiver";
        Intent intent = new Intent(ShockReceiver.SHOCK_ACTION);

        ComponentName componentName = new ComponentName(this, fullName);

        intent.setComponent(componentName);

        sendBroadcast(intent);

    }
}

 ShockReceiver

package com.tiger.chapter09.receiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.util.Log;

public class ShockReceiver extends BroadcastReceiver {

    public static final String SHOCK_ACTION="com.jmj.shock";
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent!=null&&intent.getAction().equals(SHOCK_ACTION)){
            Log.d("ning","震动一下");
            //从系统服务中获取震动管理器
            Vibrator vb = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
            //震动需要权限,开启清单权限就不会报错了
                vb.vibrate(VibrationEffect.createOneShot(500,50));
        }

    }
}

清单文件 

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

<!--    震动需要系统权限 -->
    <uses-permission android:name="android.permission.VIBRATE"/>
    
    
    <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/Theme.MyApplication">
        <receiver
            android:name=".receiver.ShockReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="com.jmj.shock"/>
            </intent-filter>

        </receiver>


        <activity
            android:name=".BroadStaticActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

</manifest>

5.系统分钟到达广播

Activity

package com.tiger.chapter09;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;

public class SystemMinuteActivity extends AppCompatActivity {

    private TimeReceiver timeReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_system_minute);
    }


    @Override
    protected void onStart() {
        super.onStart();
        //创建一个分钟变更的广播接收器
        timeReceiver = new TimeReceiver();
        IntentFilter filter = new IntentFilter(Intent.ACTION_TIME_TICK);
        registerReceiver(timeReceiver,filter);

    }

    @Override
    protected void onStop() {
        super.onStop();
        unregisterReceiver(timeReceiver);
    }
}

TimeReceiver

package com.tiger.chapter09;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class TimeReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent!=null){
            Log.d("ning","收到一个分钟到达广播");
        }
    }
}

6.系统网络变更广播

SystemNetWorkActivity

package com.tiger.chapter09;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;

import com.tiger.chapter09.receiver.NetWorkReceiver;

public class SystemNetWorkActivity extends AppCompatActivity {

    private NetWorkReceiver netWorkReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_system_net_work);
    }


    @Override
    protected void onStart() {
        super.onStart();
        netWorkReceiver = new NetWorkReceiver();
        IntentFilter filter = new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE");
        registerReceiver(netWorkReceiver,filter);

    }

    @Override
    protected void onStop() {
        super.onStop();
        unregisterReceiver(netWorkReceiver);

    }
}

NetWorkReceiver

package com.tiger.chapter09.receiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.NetworkInfo;
import android.os.Parcelable;
import android.util.Log;

import com.tiger.chapter09.util.NetworkUtil;

public class NetWorkReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent != null) {
            NetworkInfo networkInfo = intent.getParcelableExtra("networkInfo");
            // 收到一个网络变更广播,网络大类为MOBILE,网络小类为HSPA,网络制式为3G,网络状态为DISCONNECTED
            // 收到一个网络变更广播,网络大类为WIFI,网络小类为,网络制式为未知,网络状态为CONNECTED
            String text = String.format("收到一个网络变更广播,网络大类为%s," +
                            "网络小类为%s,网络制式为%s,网络状态为%s",
                    networkInfo.getTypeName(),
                    networkInfo.getSubtypeName(),
                    NetworkUtil.getNetworkClass(networkInfo.getSubtype()),
                    networkInfo.getState().toString());

            Log.d("ning", text);

        }

    }
}

NetWorkUtil

package com.tiger.chapter09.util;

import android.telephony.TelephonyManager;

public class NetworkUtil {
    // 获取数据连接的制式类型
    public static String getNetworkClass(int subType) {
        switch (subType) {
            case TelephonyManager.NETWORK_TYPE_GPRS:
            case TelephonyManager.NETWORK_TYPE_EDGE:
            case TelephonyManager.NETWORK_TYPE_CDMA:
            case TelephonyManager.NETWORK_TYPE_1xRTT:
            case TelephonyManager.NETWORK_TYPE_IDEN:
                return "2G";
            case TelephonyManager.NETWORK_TYPE_UMTS:
            case TelephonyManager.NETWORK_TYPE_EVDO_0:
            case TelephonyManager.NETWORK_TYPE_EVDO_A:
            case TelephonyManager.NETWORK_TYPE_HSDPA:
            case TelephonyManager.NETWORK_TYPE_HSUPA:
            case TelephonyManager.NETWORK_TYPE_HSPA:
            case TelephonyManager.NETWORK_TYPE_EVDO_B:
            case TelephonyManager.NETWORK_TYPE_EHRPD:
            case TelephonyManager.NETWORK_TYPE_HSPAP:
                return "3G";
            case TelephonyManager.NETWORK_TYPE_LTE:
                return "4G";
            case TelephonyManager.NETWORK_TYPE_NR:
                return "5G";
            default:
                return "未知";
        }
    }
}

 

7. alarm定时器广播

package com.tiger.chapter09.receiver;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.util.Log;

public class AlarmReceiver extends BroadcastReceiver {

    public static final String ALARM_ACTION="com.tiger.chapter09.alarm";
    private Context mContext;

    public AlarmReceiver(Context mContext) {
        this.mContext = mContext;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent != null&&intent.getAction().equals(ALARM_ACTION)){
            Log.d("ning","收到闹钟广播");
            sendAlarm();
        }
    }


    //发送闹钟广播的方法
    public void sendAlarm(){
        Intent intent = new Intent(ALARM_ACTION);
        // 创建一个用于广播的延迟意图
        // 针对 S+(版本 10000 及更高版本)要求在创建 PendingIntent 时指定 FLAG_IMMUTABLE 或 FLAG_MUTABLE 之一。
        // 强烈考虑使用 FLAG_IMMUTABLE,仅当某些功能依赖于 PendingIntent 是可变的时才使用 FLAG_MUTABLE
        PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_IMMUTABLE);
        // 从系统服务中获取闹钟管理器
        AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
            // 允许在空闲时发送广播,Android6.0之后新增的方法
            alarmManager.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, 1000, pendingIntent);
        }else{
            // 设置一次性闹钟,延迟若干秒后,携带延迟意图发送闹钟广播(但Android6.0之后,set方法在暗屏时不保证发送广播,
            // 必须调用setAndAllowWhileIdle方法)
            alarmManager.set(AlarmManager.RTC_WAKEUP, 1000, pendingIntent);
        }


        // 设置重复闹钟,每隔一定间隔就发送闹钟广播(但从Android4.4开始,setRepeating方法不保证按时发送广播)
//        alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(),
//                1000, pIntent);


    }
}
package com.tiger.chapter09;

import androidx.appcompat.app.AppCompatActivity;

import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;

import com.tiger.chapter09.receiver.AlarmReceiver;

public class AlarmActivity extends AppCompatActivity implements View.OnClickListener {

    private AlarmReceiver alarmReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_alarm);
        findViewById(R.id.btn_alarm).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        alarmReceiver.sendAlarm();
    }


    @Override
    protected void onStart() {
        super.onStart();
        alarmReceiver = new AlarmReceiver(getApplicationContext());
        IntentFilter filter = new IntentFilter(AlarmReceiver.ALARM_ACTION);
        registerReceiver(alarmReceiver,filter);

    }

    @Override
    protected void onStop() {
        super.onStop();
        unregisterReceiver(alarmReceiver);
    }
}

8.竖屏与横屏切换

 

package com.tiger.chapter09;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.content.res.Configuration;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

public class ChangeDirectionActivity extends AppCompatActivity {

    private TextView tv_monitor;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_change_direction);
        tv_monitor = findViewById(R.id.tv_monitor);
        Log.d("ning","onCreate");//只执行一次,在屏幕旋转之后
    }

    //在配置项变更是触发。比如屏幕方向发生变更等等
    @Override
    public void onConfigurationChanged(@NonNull Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        switch (newConfig.orientation){
            case Configuration.ORIENTATION_PORTRAIT:
                tv_monitor.setText("当前屏幕为竖屏方向");
                break;
            case Configuration.ORIENTATION_LANDSCAPE:
                tv_monitor.setText("当前屏幕为横屏方向");
                break;
            default:
                break;
        }

    }
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 震动需要系统权限 -->
    <uses-permission android:name="android.permission.VIBRATE" />

    <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/Theme.MyApplication">


        <receiver
            android:name=".receiver.ShockReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="com.jmj.shock" />
            </intent-filter>
        </receiver>

        <activity
            android:name=".ChangeDirectionActivity"
            android:exported="true"
            android:configChanges="orientation|screenLayout|screenSize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

</manifest>

设置只能竖屏或者横屏

 <activity
            android:name=".ChangeDirectionActivity"
            android:exported="true"
            android:configChanges="orientation|screenLayout|screenSize"
            android:screenOrientation="portrait">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

screenOrientation = portrait | landscape

9.回到桌面和使用任务列表

 
package com.tiger.chapter09;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.app.PictureInPictureParams;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.util.Rational;

public class ReturnDesktopActivity extends AppCompatActivity {

    private DesktopReceiver desktopReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_return_desktop);
    //因为按了Home或任务键 所以要在onCreate 和 Destroy 来注册 广播 要不然,stop就监听不到了
        desktopReceiver = new DesktopReceiver();
        IntentFilter filter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
        registerReceiver(desktopReceiver,filter);

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(desktopReceiver);
    }

    //在进入画中画模式或退出画中画模式时触发
    @Override
    public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode, @NonNull Configuration newConfig) {
        super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig);
        if (isInPictureInPictureMode){
            //进入了画中画模式
            Log.d("ning","进入了画中画模式");
        }else {
            //退出了画中画模式
            Log.d("ning","退出了画中画模式");
        }

    }

    //定义一个返回到桌面的广播接收器
    private class DesktopReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent != null && intent.getAction().equals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) {
                //回到桌面或者切换到任务列表的主题广播
                String reason = intent.getStringExtra("reason");
                if (!TextUtils.isEmpty(reason)
                        && (reason.equals("homekey") || reason.equals("recentapps"))) {
                    //Android 8.0 开始才提供画中画模式

                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !isInPictureInPictureMode()) {
                        //进入画中画模式 创建画中画模式的参数构造器
                        PictureInPictureParams.Builder builder = new PictureInPictureParams.Builder();
                        //设置宽高比例值,第一个参数表示分子,第二个参数表示分母
                        // 下面的10/5 =2,表示画中画窗口的宽度是高度的两倍
                        Rational rational = new Rational(10, 5);//宽 高 10 : 5
                        builder.setAspectRatio(rational);
                        //进入画中画模式
                        enterPictureInPictureMode(builder.build());
                    }
                }
            }
        }
    }


}

清单文件 开启画中画支持

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 震动需要系统权限 -->
    <uses-permission android:name="android.permission.VIBRATE" />

    <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/Theme.MyApplication">


        <receiver
            android:name=".receiver.ShockReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="com.jmj.shock" />
            </intent-filter>
        </receiver>

        <activity
            android:name=".ReturnDesktopActivity"
            android:configChanges="orientation|screenLayout|screenSize"
            android:exported="true"
            android:screenOrientation="portrait"
            android:supportsPictureInPicture="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

</manifest>

  • 9
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值