精华内容
下载资源
问答
  • spark broadcast广播变量详解
    2021-01-14 16:36:33

    为什么需要broadcast类型变量 ,它有哪些优点?

    spark中怎样创建和使用broadcast类型变量 ?

    spark中的具体实现

    1. 为什么需要broadcast类型变量 ?

    各个slave端都需要同一个数据,并且只有读取操作

    例如: 一个object对象,一个map或者bloomFilter等

    broadcast类型变量和传输一个可序列化的变量的区别 ?

    broadcast类型变量可以保证只在executor的内存中存在一份

    将要传输的变量不需要实现Serializable接口

    可以高效地传输较大的数据集

    以上3点可以在下面的实现中看到

    2. spark中怎样创建和使用broadcast ?

    具体的示例在Broadcast.scala的comment中,其中需要注意的是,一旦一个broadcast初始化好了,今后对它的值的访问只能通过broadcast间接访问,这也是一个wrapper的使用模式,例如:

    scala> val broadcastVar = sc.broadcast(Array(1, 2, 3))

    broadcastVar: org.apache.spark.broadcast.Broadcast[Array[Int]] = Broadcast(0)

    scala> broadcastVar.value

    res0: Array[Int] = Array(1, 2, 3)

    3. spark中的具体实现

    1. broadcast类型具体的方法

    1. 创建

    sc.broadcast()

    2. 读取

    value

    3. 销毁

    可重建的销毁: unpersist

    不可重建的销毁: destroy

    2. 实现机制

    目前spark中只有一种实现 TorrentBroadcast.scala

    具体机制如下:

    driver端:

    将序列化过的对象分成小块,存放在driver端的BlockManager里

    executor端:

    executor首先从自己的BlockManager去拿,如果有就直接用,如果没有执行2步

    从driver/其它executor端拉取对象的小块放入自己的BlockManager 供自己和其它的executor使用/拉取

    这样的好处是避免了driver端因为发送数据给每个executor而造成热点问题

    TorrentBroadcast 实现摘要

    TorrentBroadcast#value调用顺序:

    getValue 外部接口

    readBroadcastBlock 将读入的blocks拼成obj放入blockManager

    readBlocks 将块读取入blockManager

    broadcast变量的块的形成:

    只会在driver端形成,调用顺序

    private val numBlocks: Int = writeBlocks(obj)

    writeBlocks 将对象分成块

    executor端也会有取numBlocks这个变量,但由于不是transient的,就不会再调用writeBlocks

    ps:

    writeBlocks: 将对象切分为块,返回块的个数

    每块的id为: broadcast_1_piece2 (其中1表示broadcast的id,2表示第几个块),由于数据是在driver端收集的,然后其他executor通过byte流来拉取数据,这样就不需要broadcast的变量实现Serializable接口

    4.broadcast相关配置

    观察spark的日志输出经常会看到 auto braocast,braocast确实是自动的,你也可以手动,也可以通过配置来指定。

    广播表的最大大小被这个参数所控制 默认10M

    spark.sql.autoBroadcastJoinThreshold

    当小于该配置是,小表会被自动的广播出去。(参考的2.4.1版本)

    当大于改配置时,需要显示的广播下。

    更多相关内容
  • ps4broadcast

    2021-05-26 07:50:31
    PS5、XBOX Series X依然支持rtmp方式直播,所以ps4broadcast也支持PS5和XBOX Series X(XBOX无弹幕支持)。 PS5上使用ps4broadcast的效果非常好,自带录像功能也支持了1080p@60fps,并且PS5与PS4的弹幕重定向功能是...
  • pytorch:tensor的broadcast

    千次阅读 2020-03-05 17:37:39
    x=torch.ones(5,1,4,2) y=torch.ones(3,1,1) (x+y).size() torch.Size([5, 3, 4, 2]) 首先按尾部维度对齐 即1对2,1对4,3对1,然后没有维度能对5,就补一个维度,size为1,则1对5 每一对中,如果两个数字不一样,...

    broadcasting

    # 按照尾部维度对齐
    x=torch.ones(5,1,4,2)
    y=torch.ones(3,1,1)
    (x+y).size()
    
                       torch.Size([5, 3, 4, 2])
    
    • 首先按尾部维度对齐 即1对2,1对4,3对1,然后没有维度能对5,就补一个维度,size为1,则1对5
    • 每一对中,如果两个数字不一样,那么就把1变成另一个,比如说第一对是1对2,那么就把1变成2(代表着y在最后一个维度(列)上copy了一次)
      又比如3对1,那么就把1变成3(代表着x在第二个维度上copy了两次)
      1对5,那么就把1变成5(这个1是新增加的维度,所以1变成5就代表着把y再copy4次)
    • PS:如果一对数字中,两个数字不同,并且又没有1,那么就会报错
    a = torch.arange(6).reshape(2,1,3)
    a
    
    tensor([[[0, 1, 2]],
    
            [[3, 4, 5]]])
    
    b = torch.tensor([[100],[200],[300]])
    b
    
    tensor([[100],
            [200],
            [300]])
    
    a+b
    
    tensor([[[100, 101, 102],
             [200, 201, 202],
             [300, 301, 302]],
    
            [[103, 104, 105],
             [203, 204, 205],
             [303, 304, 305]]])
    
    a = torch.arange(1,9).reshape(2,4)
    a
    
    tensor([[1, 2, 3, 4],
            [5, 6, 7, 8]])
    
    b = torch.arange(1,3).reshape(1,2)
    b
    
    tensor([[1, 2]])
    
    • 现在a的size是24 b的size是12 如果进行broadcast,那么其中一对就是2对4,所以不能进行broadcast,那么怎么办呢?
      先把b的第二个维度(列)copy一次,让他变成1*4
    b=b.repeat(1,2)
    
    a+b
    
    tensor([[ 2,  4,  4,  6],
            [ 6,  8,  8, 10]])
    
    
    
    
    
    a = torch.full((2,3,2),90) #2个班级,每个班级3名学生,每个学生考了两门考试,假设目前都是90分
    a
    
    tensor([[[90., 90.],
             [90., 90.],
             [90., 90.]],
    
            [[90., 90.],
             [90., 90.],
             [90., 90.]]])
    
    • 现在我们想给第二个班级的所有人加5分,使用broadcast
    b = torch.tensor([0.,5.]).reshape(2,1,1)
    b
    
    tensor([[[0.]],
    
            [[5.]]])
    
    a + b 
    
    tensor([[[90., 90.],
             [90., 90.],
             [90., 90.]],
    
            [[95., 95.],
             [95., 95.],
             [95., 95.]]])
    
    • 如果想给每个班的第1个同学加5分:
    b = torch.tensor([5.,0.,0.]).reshape(1,3,1)
    b
    
    tensor([[[5.],
             [0.],
             [0.]]])
    
    a + b
    
    tensor([[[95., 95.],
             [90., 90.],
             [90., 90.]],
    
            [[95., 95.],
             [90., 90.],
             [90., 90.]]])
    
    • 如果想给每个同学的第1门功课加5分:
    b = torch.tensor([5.,0.]).reshape(1,1,2)
    b
    
    tensor([[[5., 0.]]])
    
    a + b
    
    tensor([[[95., 90.],
             [95., 90.],
             [95., 90.]],
    
            [[95., 90.],
             [95., 90.],
             [95., 90.]]])
    
    
    
    展开全文
  • 1、什么是安卓的Broadcast?安卓的四大组件之一,是一种广泛应用在应用程序之间传输信息的机制。2、什么是安卓的BroadcastReceiver?是对发送出来的广播进行过滤接收并响应的一类组件,它就是用来接收来自系统和应用...

    1、什么是安卓的Broadcast?

    安卓的四大组件之一,是一种广泛应用在应用程序之间传输信息的机制。

    2、什么是安卓的BroadcastReceiver?

    是对发送出来的广播进行过滤接收并响应的一类组件,它就是用来接收来自系统和应用中的广播。例如系统的广播有开机广播: 系统在开机时候会发送开机广播,程序接收到之后,能进行开机自启动。 网络状态改变广播: 3g变wifi、网络断开等。电量改变广播等等。。。

    3、Anroid为什么要这样设计?

    大大减少开发工作量和开发周期
    作为开发者,只需要掌握BroadcastReceiver

    4、怎么理解Broadcast和BroadcastReceiver ?

    Broadcast就像现实中的广播电台,他发广播信号来,然后我们用收音机来接收,然后处理,并且播放出声音, BroadcastReceiver就相当于那台收音机。

    5、使用方法

    • 发送:

    把信息装入一个Intent对象(如:Action、Category),通过调相应的方法将Intent对象以广播的方式发送出去:
    sendBroadcast();
    sendOrederBroadcast();
    sendStickyBroadcast();

    • 接收:

    当Intent发送之后,所有已经注册receivedBroadcastReceiver会检查注册时的IntentFilter是否与发送的Intent相匹配,若匹配则就会调用BroadcastReceiver的onReceiver()方法。所以当我们定义一个BroadcastReceiver的时候,都需要实现onReceiver()方法。

    • 注意:

    BroadcastReceiver需要注册
    静态注册
    代码动态注册

    6、注意!!!!

    BroadReceiver生命周期只有十秒左右,不能直接执行耗时操作,不然会出现ANR(应用程序无响应),也不能用子线程来做,因为每次广播来的时候都会创建一个Reveiver对象,并且调用onReceiver,执行完之后 ,对象会立刻被销毁,子线程也没了
    要做耗时操作的话,应该通过发送Intent给Service,由Service来完成。
    动态注册广播接受者的话要在Destory回调事件进行unregister

    7、广播的分类

    • 普通广播 (Normal broadcast)
    • 所有监听该广播接受者都可以监听到该广播
    • 同级别接收先后顺序是随机的(无序)
    • 级别低的后收到广播
    • 接收器不能截断广播的继续传播,也不能处理广播
    • 同级别动态注册高于静态注册
    • 有序广播 (Oredered broadcast)
    • 按照接收者的优先顺序来接收广播,优先级别在intent-filter中的priority中声明,-1000到1000之间,值越大优先级越高,可以终止广播的继续传播,接受者可以修改intent的内容。
    • 同级别接收顺序是随机的
    • 级别低的后收到
    • 能截断广播的继续传播,高级别的广播接收器接收广播后能决定时候截断。
    • 能处理广播
    • 同级别动态注册高于静态注册
    • 异步广播 (粘滞性滞留广播) ps:已被弃用
    • 不能处理结果给下一个接收者,无法终止广播。
    • 一直存在
    • 可以先发送广播,再注册接收器
    • 需要在清单文件添加android.permission.BROADCAST_STICKY权限

    8、Demo

    布局actibity_main三个按钮:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <Button
            android:id="@+id/bt_one"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:text="普通广播" />
    
        <Button
            android:id="@+id/bt_two"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:text="有序Ordered广播" />
    
        <Button
            android:id="@+id/bt_three"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:text="异步广播Sticky粘滞性滞留广播" />
    
    </LinearLayout>

    MainActivity.java

    public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    
        private Button btOne;
        private Button btTwo;
        private Button btThree;
    
    
        MyReiceiverThree myReiceiver = new MyReiceiverThree();
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            btOne = (Button) findViewById(R.id.bt_one);
            btTwo = (Button) findViewById(R.id.bt_two);
            btThree = (Button) findViewById(R.id.bt_three);
    
            btOne.setOnClickListener(this);
            btTwo.setOnClickListener(this);
            btThree.setOnClickListener(this);
    
    
            //动态注册,在当前activity的生命周期內运行
            /*IntentFilter filter= new IntentFilter(Config.BC_ONE_ACTION);
            MyReiceiver myReiceiver = new MyReiceiver();
            registerReceiver(myReiceiver,filter);*/
    
        }
    
        @Override
        public void onClick(View view) {
            Intent intent = new Intent();
            switch (view.getId()){
                case R.id.bt_one:      //发送普通广播
                    intent.setAction(Config.BC_ONE_ACTION);
                    intent.putExtra("msg","这是普通广播");
                    sendBroadcast(intent);
                    break;
                case R.id.bt_two:     //有序广播
                    intent.setAction(Config.BC_TWO_ACTION);
                    intent.putExtra("msg","这是有序广播");
                    sendOrderedBroadcast(intent,null);  //其中第二个参数是设置权限,即接收器必须具有相应的权限才能正常接收到广播。
                    break;
                case R.id.bt_three:   //异步广播
                    intent.setAction(Config.BC_THREE_ACTION);
                    intent.putExtra("msg","这是异步广播");
                    sendStickyBroadcast(intent);
    
                    //可以先发送 后注册
                    IntentFilter filter = new IntentFilter(Config.BC_THREE_ACTION);
    
                    registerReceiver(myReiceiver, filter);
                    break;
            }
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            unregisterReceiver(myReiceiver);
        }
    }
    

    MyReceiver.java

    public class MyReiceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
    
            //获取处理的的广播,普通广播不能获取处理
            //true代表如果前面的接收器没有存放数据,则自动创建一个空的Bundle对象,false则表示如果前面的接收器如果没有存放任何数据则返回null。
            Bundle  bundle= getResultExtras(true);
            System.out.println("接收器1接收到处理的值:"+bundle.getString("msg"));
    
            System.out.println("接收器1:"+intent.getStringExtra("msg"));
        }
    }

    MyReceiverTwo.java

    public class MyReiceiverTwo extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            //Toast.makeText(context,intent.getStringExtra("msg"),Toast.LENGTH_SHORT).show();
            System.out.println("接收器2:"+intent.getStringExtra("msg"));
    
            abortBroadcast();    //截断广播,不让别的接收器继续接收,有序广播才能成功拦截
    
            //处理广播
            Bundle bundle = new Bundle();
            bundle.putString("msg","处理过后的广播");
            setResultExtras(bundle); //
        }
    }

    MyReceiverThree.java

    public class MyReiceiverThree extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            //Toast.makeText(context,intent.getStringExtra("msg"),Toast.LENGTH_SHORT).show();
            System.out.println("接收器3:"+intent.getStringExtra("msg"));
    
        }
    }

    Config.java

    public class Config {
        public static final String BC_ONE_ACTION = "com.example.testbroadcasetwo.bcone";
        public static final String BC_TWO_ACTION = "com.example.testbroadcasetwo.bctwo";
        public static final String BC_THREE_ACTION = "com.example.testbroadcasetwo.bcthree";
    }

    Androidmanifest.xml

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.testbroadcasetwo">
    
        //异步广播需要 一个权限
        <uses-permission android:name="android.permission.BROADCAST_STICKY" />
    
        <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">
            <activity android:name=".MainActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
    
            //静态注册,全局有效
            //第一个接收器
            <receiver android:name=".MyReiceiver">
                <intent-filter android:priority="10">//添加级别
                    <action android:name="com.example.testbroadcasetwo.bcone" />
                </intent-filter>
            </receiver>
    
            //第二个接收器
            <receiver android:name=".MyReiceiverTwo">
                <intent-filter android:priority="11">//添加级别
                    <action android:name="com.example.testbroadcasetwo.bcone" />
                </intent-filter>
            </receiver>
    
    
        </application>
    
    </manifest>

    Demo下载地址: http://download.csdn.net/detail/niubitianping/9577865

    9、onReceiver回调更新ui
    注意: 必须使用动态注册才能实现回调更新ui
    目录结构:
    这里写图片描述

    Confiug.java 定义一个常量作为action

    public class Config {
        public static String BC_ONE = "com.example.testbroadcast.bcone";
    }

    TYPE.java 枚举类,集合,没用了,用来判断是什么广播的

    public enum TYPE {
        NORMAL
    }

    HandleBroadcas.java p层的处理数据类

    public class HandleBroadcast {
    
        private IShowView iShowView;
        private Context context;
    
        public HandleBroadcast(final IShowView iShowView, Context context) {
            this.iShowView = iShowView;
            this.context = context;
    
            //必须动态注册才能实现回调
            MyBroadcastReceiver broadcast = new MyBroadcastReceiver();
            IntentFilter intentFilter = new IntentFilter();
            intentFilter.addAction(Config.BC_ONE);
            context.registerReceiver(broadcast, intentFilter);
    
    
            broadcast.setiShowView(new IShowView() {
                @Override
                public void updateText(String msg) {
                    iShowView.updateText(msg);
                }
            });
        }
    
    
        public void sendMyBroadcast(TYPE type) {
    
            Intent intent = new Intent();
            switch (type) {
                case NORMAL:   //普通广播
                    intent.putExtra("msg", "普通广播发送成功");
                    intent.setAction(Config.BC_ONE);
                    context.sendBroadcast(intent);
                    break;
            }
        }
    
    }

    MyBroadcast.java 广播接收器

    public class MyBroadcastReceiver extends BroadcastReceiver {
    
        private IShowView iShowView;
    
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            String msg = intent.getStringExtra("msg");
            iShowView = (MainActivity) context;
            if (action.equals(Config.BC_ONE)) { //接收到普通广播
                iShowView.updateText(msg);    //回调给HandleBroadcast
            }
        }
    
        public void setiShowView(IShowView iShowView) {
            this.iShowView = iShowView;
        }
    }

    IShowView.java 回调到activity更新ui的接口

    public interface IShowView {
    
        void updateText(String msg);
    
    }

    MainActivity.java

    public class MainActivity extends AppCompatActivity implements View.OnClickListener,IShowView{
    
        private Button btOne;
    
        private TextView mTvResult;
    
        //p层,处理数据
        private HandleBroadcast handleBroadcast;
    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            handleBroadcast = new HandleBroadcast(this,this);
    
            btOne = (Button) findViewById(R.id.bt_one);
            mTvResult = (TextView) findViewById(R.id.tv_result);
            btOne.setOnClickListener(this);
        }
    
        @Override
        public void onClick(View view) {
            switch (view.getId()){
                case R.id.bt_one:
                    handleBroadcast.sendMyBroadcast(TYPE.NORMAL);
                    break;
            }
        }
    
    
        /**
         * 广播接收处理完毕之后回调更新ui
         * @param msg 要显示的文字
         */
        @Override
        public void updateText(String msg) {
            mTvResult.setText(msg);
        }
    }

    activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <Button
            android:id="@+id/bt_one"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:text="发送广播"
            />
        <TextView
            android:id="@+id/tv_result"
            android:layout_width="match_parent"
            android:layout_height="60dp"
            android:text="结果"
            android:gravity="center"
            />
    </LinearLayout>

    mvp模式的demo下载:http://download.csdn.net/detail/niubitianping/9577879

    展开全文
  • 广播——broadcast

    千次阅读 2016-05-27 17:52:13
    Ps:这里有一点需要注意的是,同等优先级的静态接收器的接收顺序具有不确定性,原因就是File.list()的方法返回的顺序具有不确定性,如果需要查看某接收器的接收顺序,最好是试验大量的 apk 名。 ordered 广播 ...

    广播机制简介

    广播是一种可以跨进程的通信方式(比如:接收系统广播)。

    Android 广播不关心接收者是否收到处理或者如何处理广播,可以说是一种单向的通知。Android 通过 BraodcastReceiver 来监听系统发出的广播,不同的 BraodcastReceiver 通过设置不同的 fliter 来区分监听广播的类型。有些广播的监听需要相应的权限。

    广播分类

    1. 标准广播(Normal Broadcast)
    2. 有序广播(Ordered Broadcast)

    标准广播

    标准广播:完全异步执行的广播,在广播发生之后,所有广播同一时间接收到广播消息,无任何先后顺序,效率高,但无法被截断。
    这里写图片描述

    有序广播

    有序广播:同步执行的广播,广播发出后,同一时刻只有一个广播接收器能收到这条广播消息,当这个广播接收器中的逻辑执行完毕后,广播才会继续传递,广播接收器有先后顺序,优先级高的先收到,且可以截断,后面的无法接收。
    这里写图片描述

    接收系统广播

    BraodcastReceiver 必须经过注册才能具有监听功能,注册的方式有两种:
    广播注册方式:在代码中注册,又称动态注册。以及在AndroidManifest.xml清单文件中注册。

    动态注册监听网络变化

    (1)创建广播接收器
    新建一个内部类,让他继承BroadcastReceiver,并重写父类的onReceive()方法。
    (2)代码注册广播。
    (3)代码举例

    public class MainActivity extends Activity {
    
        IntentFilter intentFilter;
        MyBroadcastReceiver myReceiver;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            intentFilter = new IntentFilter();
            intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
            myReceiver = new MyBroadcastReceiver();
            //注册广播
            registerReceiver(myReceiver, intentFilter);
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            unregisterReceiver(myReceiver);
        }
    
        class MyBroadcastReceiver extends BroadcastReceiver{
            @Override
            public void onReceive(Context context, Intent intent) {
                ConnectivityManager cm = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
                NetworkInfo networkInfo = cm.getActiveNetworkInfo();
                Toast.makeText(MainActivity.this, "i am change" + networkInfo.getState(), Toast.LENGTH_LONG).show();
            }
        }
    }
    

    添加获取网络状态的权限。

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>

    静态注册实现开机启动

    (1)动态注册的缺点:必须在程序开启时才能接收广播。
    (2)所以,静态注册解决了这个问题。
    静态注册步骤:

    • 新建一个类继承BroadcastReceiver,实现onReceiver(),不再是内部类。
    • 在AndroidManifest.xml中注册,此时是作为四大组件,用标签,加上等,注意也要加上相关需要的权限。

    BootCompleteReceiver .java

    public class BootCompleteReceiver extends BroadcastReceiver {
    
        @Override
        public void onReceive(Context context, Intent intent) {
            Toast.makeText(context, "Boot Complete", Toast.LENGTH_LONG).show();
        }
    
    }
    权限
    
        <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    注册
    <receiver android:name=".BootCompleteReceiver" >
                <intent-filter>
                    <action android:name="android.intent.action.BOOT_COMPLETED" />
                </intent-filter>
            </receiver>

    注意耗时操作

    不要在onReceive()中添加过多的逻辑或者进行耗时操作。因为广播接收器不允许开启线程,当onReceive()运行较长时间而没结束时,程序会报错。8s左右即可,超过就要考虑转移处理。(比如在这里面启动一个服务,在服务中进行操作?)。

    发送自定义广播

    1. 在清单文件中注册及对应的action。
    2. 在使用的地方sendBroadcast(intent)
      intent构造函数传入action作为参数(String)。同时,用intent还可以携带数据。
    Intent intent = new Intent(
                            "com.example.broadcasttest.MY_BROADCAS");
    sendBroadcast(intent);
    public class MyBroadcastReceiver extends BroadcastReceiver {
    
        @Override
        public void onReceive(Context context, Intent intent) {
            Toast.makeText(context, "received in MyBroadcastReceive",
                    Toast.LENGTH_SHORT).show();
        }
    
    }
    //这里的action是自定义的,不是android自带
    <receiver android:name=".MyBroadcastReceiver">
                <intent-filter>
                    <action android:name="com.example.broadcasttest.MY_BROADCAST"/>
                </intent-filter>
            </receiver>

    注意:在这之前的广播都属于标准广播

    发送有序广播

    发送有序广播步骤

    • sendOrderBroadcast(intent, null)
    • 注册时,进行设置优先级。或者通过调用 IntentFilter 对象的 setPriority()进行设置。
    • 截断:优先级高的接收器中调用abortBroadcast(),后面的接收器就接收不到了。

    优先级

    • 范围:-1000~1000,但是实际最大值是可以达到int的最大值2147483647。

    使用本地广播

    出现原因

    前面发送和接收的广播均属于系统全局广播,即发出的广播可以被其他任何程序接收到,且我们也可以接收其他程序的广播。这就导致了安全性问题(比如关键数据或者是垃圾广播)。
    所以,引入本地广播机制,只能在应用程序内部进行传递,本地广播机制中的广播接收器也只能接收来自本应用发出的广播。

    本地广播使用

    1. LocalBroadcastManager来对广播进行管理。
    2. LocalBroadcastManager localBroadcastManager;
      localBroadcastManager = LocalBroadcastManager.getInstance(this);
    3. localBroadcastManager.sendBroadcast(intent);
    4. //注册本地广播监听器localBroadcastManager.registerReceiver(localReceiver, intentFilter);
    5. localBroadcastManager.unregisterReceiver(localReceiver);
      代码:
    public class MainActivity extends Activity {
    
        private IntentFilter intentFilter;
    
        private LocalReceiver localReceiver;
    
        private LocalBroadcastManager localBroadcastManager;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            localBroadcastManager = LocalBroadcastManager.getInstance(this);
            Button button = (Button) findViewById(R.id.button);
            button.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent(
                            "com.example.broadcasttest.LOCAL_BROADCAST");
                    localBroadcastManager.sendBroadcast(intent);
                }
            });
            intentFilter = new IntentFilter();
            intentFilter.addAction("com.example.broadcasttest.LOCAL_BROADCAST");
            localReceiver = new LocalReceiver();
            localBroadcastManager.registerReceiver(localReceiver, intentFilter);
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            localBroadcastManager.unregisterReceiver(localReceiver);
        }
    
        class LocalReceiver extends BroadcastReceiver {
    
            @Override
            public void onReceive(Context context, Intent intent) {
                Toast.makeText(context, "received local broadcast",
                        Toast.LENGTH_SHORT).show();
            }
    
        }
    
    }
    

    优点

    本地广播是无法通过静态注册的方式来接收的。其实这也完全
    可以理解,因为静态注册主要就是为了让程序在未启动的情况下也能收到广播,而发送本地
    广播时,我们的程序肯定是已经启动了,因此也完全不需要使用静态注册的功能。
    最后我们再来盘点一下使用本地广播的几点优势吧。
    1. 可以明确地知道正在发送的广播不会离开我们的程序,因此不需要担心机密数据泄
    漏的问题。
    2. 其他的程序无法将广播发送到我们程序的内部,因此不需要担心会有安全漏洞的隐
    患。
    3. 发送本地广播比起发送系统全局广播将会更加高效。

    广播优先级

    基本原则

    接收无序广播的接收器接收到广播的顺序是有序的(由优先级决定顺序)
    接收无序广播的接收器也一样可以设置优先级的
    动态注册广播优先级高于静态注册广播
    同等优先级的动态接收器,先注册的先接收
    同等优先级的静态接收器,接收广播的顺序与 String[] java.io.File.list()顺序一致
    Ps:这里有一点需要注意的是,同等优先级的静态接收器的接收顺序具有不确定性,原因就是File.list()的方法返回的顺序具有不确定性,如果需要查看某接收器的接收顺序,最好是试验大量的 apk 名。

    ordered 广播

    假设有如下优先级的 5 个接收器
    1.动态 A(优先级=1)
    2.动态 B(优先级=2)
    3.动态 C(优先级=2)
    4.静态 D(优先级=1)
    5.静态 E(优先级=2)
    并且 B 先于 C 注册
    那么实际接收顺序应为
    B C E A D
    也就是说,如果静态接收器的优先级高于动态接收器的优先级,那么还是静态接收器先接收到广播(比如接收 SMS 广播)

    非 ordered 广播

    动态接收器高优先级>动态接收器低优先级>静态接收器高优先级>静态接收器低优先级

    只能动态接受广播源码分析

    有些广播,我们无法用静态接收器接收,比如 ACTION_SCREEN_ON,当屏幕被点亮的时候系统发送此广播。

    void com.android.server.PowerManagerService.initInThread()
    Java 代码
    void initInThread() {
    ??
    mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON);
    mScreenOnIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
    mScreenOffIntent = new Intent(Intent.ACTION_SCREEN_OFF);
    mScreenOffIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
    ??
    }

    Intent 中都设置了 Intent.FLAG_RECEIVER_REGISTERED_ONLY,所以,如果要接收,必须动态注册广播接收器 ACTION_SCREEN_OFF 也是如此。类似的还有:ACTION_TIME_TICK、ACTION_BATTERY_CHANGED。

    不能静态注册的广播:

      android.intent.action.SCREEN_ON

      android.intent.action.SCREEN_OFF

      android.intent.action.BATTERY_CHANGED

      android.intent.action.CONFIGURATION_CHANGED

      android.intent.action.TIME_TICK

    目的

    很多病毒程序为了保证自己被终止后能够再次运行,都会在xml中注册一些系统广播,企图利用这些系统高频广播来实现自启动。
    比如在老版本的android系统中,病毒程序可以通过监听TIME_TICK来启动自己的service后台运行,做一些隐秘的工作,而且就算自己被kill掉了,也能很快重新启动。
    而一旦这些系统广播加了flag FLAG_RECEIVER_REGISTERED_ONLY,这些病毒程序就没辙了。google的这一改动无疑提升了android系统的安全性。

    参考:http://blog.csdn.net/gemmem/article/details/8859493

    广播注册过程分析

    静态注册 Receiver 的流程

    静态 receiver 的注册是由 PackageManagerService 开机的时候负责初始 PMS 在开机的时候会对系统一些目录逐个扫描,解析 apk 文件。静态广播接收器就是在 PMS 做这件事情的时候顺便处理的。
    PMS 会解析 apk 的 manifest 文件,查找这里注册的 receiver,然后加载到内存中。
    PMS 初始化扫描目录的顺序:
    system/framework
    system/app
    vendor/app
    data/appd
    rm/app-private
    我们看到了 PMS 如何在初始化的时候如何解析 manifest 并把其中的 element 存放到内存中的其中receiver 保存到了 owner 的成员变量 receivers 中,owner 的类型是
    android.content.pm.PackageParser.Package 也就是说 scanPackageLI 返回结果就是已经包含了manifest 信息的 Package 对象。

    动态注册 Receiver 的流程

    动态注册最终会调用到 AMS 中的 registerReceiver 函数,最终所有动态注册的 receiver 都保存到 AMS 的成员变量 mReceiverResolver 中。静态广播和动态广播如何注册的,我们已经全部分析完了。静态广播是 PackageManagerService负责,保存到其成员变量 mReceivers 中,动态广播是 ActivityManagerService 负责,保存到其成员变量 mReceiverResolver 中。

    广播发送过程分析

    分析

    Context 中的 sendBroadCast 函数的实现是在 ContextImpl 中,和发送广播相关的有如下六个函数:
    void android.app.ContextImpl.sendBroadcast(Intent intent)
    void android.app.ContextImpl.sendBroadcast(Intent intent, String receiverPermission)
    void android.app.ContextImpl.sendOrderedBroadcast(Intent intent, String receiverPermission)
    void android.app.ContextImpl.sendOrderedBroadcast(Intent intent, String receiverPermission,
    BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData,
    Bundle initialExtras)
    void android.app.ContextImpl.sendStickyBroadcast(Intent intent)
    void android.app.ContextImpl.sendStickyOrderedBroadcast(Intent intent, BroadcastReceiver
    resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle
    initialExtras)

    可以分为 3 组:1 普通广播;2 Ordered 广播;3 Sticky 广播。不论哪种,最后都会由 AMS 处, 如果是非 ordered 广播,那么 mParallelBroadcasts 将存储所有动态接收器,然后合并的时候,mParallelBroadcasts 设置为 null,所以不会合并到 receivers 中,如果是 ordered 广播,那么mParallelBroadcasts 将合并到 receivers 中,然后,不管是哪种广播,最后都是调用scheduleBroadcastsLocked 继续处理,最终到 processNextBroadcast 函数上。广播是否有序,即通过 Boolean 变量 ordered 进行设置。

    总结

    发送过程情况分为两种(scheduleBroadcastsLocked),ordered 广播和非 ordered 广播、非ordered 广播。先处理动接收器,然后处理静态接收器 ordered 广播同时处理动态接收器和静态接收器先将动态接收器与静态接收器合并,保持着与优先级相同的顺序,优先级高的在前面,否则顺序不变。静态接收器与动态接收器优先级相同的话,动态接收器在前。

    参考

    http://www.2cto.com/kf/201408/325326.html

    自己动手

    控制activity

    public class ActivityControl {
        public static List<Activity> activityList =  new ArrayList<Activity>();
    
        public static void addActivity(Activity activity){
            activityList.add(activity);
        }
    
        public static void rmActivity(Activity activity){
            activityList.remove(activity);
        }
    
        public static void finishAllActivity(){
            int length = activityList.size();
            for(int i = 0; i < length; i++ ){
                activityList.get(i).finish();
            }
        }
    }

    强制下线(静态注册)

    offBtn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent(DownActivity.this, OffLineBroadcast.class);
                    sendBroadcast(intent);
                }
            });
    //注意,在activity外部跳转activity注意加上FLAG:Intent.FLAG_ACTIVITY_NEW_TASK
    public class OffLineBroadcast extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            ActivityControl.finishAllActivity();
            Intent i = new Intent(context, MainActivity.class);
            i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(i);
        }
    }
    清单文件注册
    <receiver android:name=".OffLineBroadcast"></receiver>

    或者在启动广播的时候用intent(action)

    Intent intent = new Intent("com.zzz.offLine");
                    sendBroadcast(intent);

    这种情况下清单文件注册注意加上action

    <receiver android:name=".OffLineBroadcast">
                <intent-filter>
                    <action android:name="com.zzz.offLine"></action>
                </intent-filter>
    </receiver>

    增加对话框提示

    public class OffLineBroadcast extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            final Context theContext = context;
            AlertDialog.Builder builder = new AlertDialog.Builder(context);
            builder.setTitle("Warning");
            builder.setMessage("You are forced to be offline, please try to login again.");
            builder.setCancelable(false);
            builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    ActivityControl.finishAllActivity();
                    Intent i = new Intent(theContext, MainActivity.class);
                    i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    theContext.startActivity(i);
                }
            });
    
            AlertDialog alertDialog = builder.create();
            //需要设置AlertDialog的类型,保证在广播接收器中可以正常弹出。
            alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
    
            alertDialog.show();;
    
        }
    }
    

    ===============================

    强制下线(动态注册)
    动态注册:广播是内部类,并且要注意广播的注册和解除,触发广播用intent(action),系统广播的触发intent不需要我们写。

    public class DownActivity extends BaseActivity {
    
        private Button offBtn;
        private DyOffBroadcast broadcast;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_down);
            initView();
    
            broadcast = new DyOffBroadcast();
            IntentFilter filter = new IntentFilter();
            filter.addAction("com.zzz.offLine");
            registerReceiver(broadcast, filter);
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            unregisterReceiver(broadcast);
        }
    
        private void initView(){
            offBtn = (Button)findViewById(R.id.offLine);
            offBtn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent("com.zzz.offLine");
                    sendBroadcast(intent);
                }
            });
        }
    
    
    
        public class DyOffBroadcast extends BroadcastReceiver {
            @Override
            public void onReceive(Context context, Intent intent) {
                ActivityControl.finishAllActivity();
                Intent i = new Intent(context, MainActivity.class);
                context.startActivity(i);
            }
        }
    }
    
    //多加一个对话框提示
    (为什么用AlertDialog.Builder而不是AlertDialog呢?AlertDialog.Builder是AlertDialog的一个公开的静态内部类,每个方法返回值都是builder,可以连续性设置,方便,参考设计模式——建造者模式。)
    AlertDialog.Builder builder = new AlertDialog.Builder(context)
                .setTitle("Warning")
                .setMessage("You are forced to be offline, please try to login again.")
                .setCancelable(false)
                .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        ActivityControl.finishAllActivity();
                        Intent i = new Intent(theContext, MainActivity.class);
                        theContext.startActivity(i);
                    }
                });
                builder.create().show();
    展开全文
  • 4. 开发流程 4.1 数据准备 4.2 ip日志信息 在ip日志信息中,我们只关系ip这一维度就可以了,其他的不做介绍 4.3 城市ip段信息 5. 代码开发 5.1 思路 加载城市ip段信息, 获取ip起始数字和结束数字,...
  • Sony’s PlayStation 4 has voice commands, just like the Xbox One. They’re just not as heavily ... PS4 voice commandswork with a standard headset, so you don’t need any special hardware–unlike ...
  • spark broadcast变量思考

    2018-07-31 17:32:45
    方法1 : val map = sc.textFile("/test.txt").map(line =&gt; { val arr = line.split("...var mapBC = sc.broadcast(map.take(10).toMap) mapBC.unpersist mapBC = sc.broad...
  • ps:我的列表存储的都是二维矩阵,其中一个维度相同,另一个维度不同,我沿着相同的维度串联完后保存 2)方法2. 把list转换为字典dict,然后保存字典,应该能解决这个问题。 参考:numpy报ValueError: could not ...
  • 当运行$ peer chaincode invoke -C mychannel -n food -c '{"Args":["userRegister","haha","haha"]}'时出现错误,Error: error getting broadcast client: orderer client failed to connect to orderer.example....
  • 本篇文章的内容都是作者通过阅读BroadCast的官方文档并结合自己的开发经验整理而成的。 英文好的同学请移步,看官方文档之前,我还是建议大家看一下这篇文章,因为这篇的整体的结构和每个知识的说明我都整理了一番...
  • 转载自:...     通过命令行执行adb shell am broadcast发送广播通知。   adb shell am broadcast 后面的参数有: [-a &lt;ACTION&gt;] [-d &lt;DATA_...
  • Android 通过adb shell am broadcast发送广播
  • Android组件(Broadcast Receiver)

    千次阅读 2016-06-14 08:55:33
    1.目录:  1.BroadcastReceiver定义  2.BroadcastReceiver作用(能干嘛?) ... 4.BroadcastReceiver分类及对比  5.BroadcastReceiver发送与接收  6.常用的系统广播   2.BroadcastReceiver定义
  • The default action for taking a screenshot on the PS4 (or PS4 Pro) is to long-press the Share button on the controller—since a regular tap will just open the share menu. There’s a setting called ...
  • 例如:adb shell am broadcast -a trans.intent.action.chameleon.CHANGE_COLOR --ei changeColorType 1 -a======动作 --ei=======key和value值 1代表黑色 0代表白色 通过命令行执行adb shell am ...
  • 3、当发送到ActivityManagerService所运行的线程的消息队列中BROADCAST_INTENT_MSG消息被处理时,ActivityManagerService就会从广播调度队列中找到需要的广播的接收者,并且将对应的广播发送给它们所运行的应用程序...
  • protected-broadcast 系统应用自定义广播规范 一、android:sharedUserId=”android.uid.system” 系统中所有使用android.uid.system作为共享UID的APK,都会首先在manifest节点中增加 android:sharedUserId=”...
  • 服务器规划 由于我电脑资源有限,我这里在4台服务器上搭建高可用环境,大家可以按照本文将环境扩展到更多的服务器,搭建步骤都是一样的。 主机名 IP地址 安装的服务 binghe151 192.168.175.151 Mycat、Zookeeper、...
  • ps】显示进程的自身标识信息 【rm /path/filename】从终端删除一个文件 【mkdir】新建一个目录或者文件 【grep】查找特定内容 【ls】显示当前目录下的文件 【cd】切换当前目录 【chmod】更改...
  • h264 ps流vlc播放

    2019-09-29 10:46:46
    ps流打包中I帧和P帧打包略有差异:I帧:ps头+ps系统头+ps map+PES头+H264 raw data,P帧:pes头+H264 raw data (P帧也可以加上ps头+ps map不影响播放)。可以用VLC播放器转码MP4文件(vlc功能真的很强大...
  •  BroadcastIntent与Intent一样是通信的媒介,与Intent不同的是Broadcast Intent同时被多个组件接收。  BroadcastIntent广播机制,广播源发出消息,通过AMS(Activity manager service),可以使多个组件接...
  • ps:这个方法要有support-v4.jar包才行 方法 二、指定某一个应用允许接收。 解决方案:intent 指定包名Intent.setPackage设置广播仅对相同包名的有效 优点: 1.支持跨进程 2.receiver可以是静态注册...
  • protected-broadcast 系统应用自定义广播规范 一、android:sharedUserId=”android.uid.system” 系统中所有使用android.uid.system作为共享UID的APK,都会首先在manifest节点中增加 android:sharedUserId=”...
  • Android四大组件Broadcast Receiver详解

    千次阅读 2015-09-30 09:59:06
    4、对于OrderedBroadcast而言,系统会根据接收者生命的优先级别顺序逐个执行接收者,优先接收到Broadcast的接收者可以终止Broadcast,调用BroadcastReceiver的abortBroadcast()方法即可终止Broadcast。如果...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 20,041
精华内容 8,016
关键字:

ps4broadcast

友情链接: PCDemo(flexible).zip