android单双页模式 android的广播接收器BroadcastReceiver android(本地广播 标准广播 有序广播)
2017/3/8 记载
单双页模式
单页模式:手机的屏幕智能显示一页的效果。双页模式:平板的屏幕可以显示两页的效果。
***也就是要保证不同的用户再体验软件的时候,软件可以自动单双页切换。
主要有两种方式:
1.在res下新建一个资源包(layout-large双页布局文件),当检测到是平板大屏幕的时候
加载这个包下的布局文件。
2.上面一种方式有缺陷,那就是这个屏幕多大才加载双页布局文件,large就是最小限定符
如果新建的资源包名为layout-sw600dp,则可以检测到大于600的就加载这个资源包下的布局文件。
四大组件之二:BroadcastReceiver(广播接收器)
分类:1.标准广播(normal broadcasts):一条广播器的消息。同一时所有的广播器都收得到这条消息。效率很高,但是不可阻断。
2.有序广播(Ordered broadcasds):同步执行的广播,一条一条的广播,只能一个一个的接收。
注册:
1.代码中注册(动态注册)
2.AndroidMainfest.xml中注册(静态注册)
优缺点:动态注册可以自由的控制注册和注销广播,但是必须是进入程序才能执行onCreate()
静态注册可以在程序为开机的情况下接收到广播,但是就是不够灵活控制。
在方法RegisterReceiver(广播类,意图intentFilter)中注册广播,广播类继承了BroadcastReceiver的类(重新onReceiver方法,广播逻辑在其中实现)。
注意:动态注册的广播器一定要取消注册(默认onDestory()中的unregisterReceiver(广播类)方法)
android.net.conn.CONNECTIVITY_CHANGE :网络发生变化的时候会发出这样的一条广播
网络监测代码图:
静态注册:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.ldp.com.broadcastreceiverproject">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/><!--网络权限-->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/><!--监听系统开机-->
<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标签来注册权限,而动态注册是不需要的。只需要在上面标注一下-->
<receiver
android:name=".BBootCompleteReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
</application>
</manifest>
注意:
广播中的 onReceive()方法不要写过多的逻辑或者耗时的语句,在广播接收器汇总是不允许开启线程的。
例子:发送标准广播
新建项目MyBroadcastReceiverProject新建一个广播类MyBroadcastReceiver
package com.example.ldp.com.broadcastreceiverproject;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
Toast.makeText(context,"AAAAA GetMyBroadcastReceiver",Toast.LENGTH_SHORT).show();
Log.d(MainActivity.ACTIVITY_SERVICE,"成功接收");
}
}
这个时候的注册信息就会自动加载到AndroidMainfest.xml中
<receiver
android:name=".MyBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.example.ldp.com..MY_BROADCAST"/>
<!--这个是随便写的相当于口令-->
</intent-filter>
修改activity_main.xml 用按钮点击发送广播
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button"
android:text="Send Broadcast"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
修改MainActivity
package com.example.ldp.com.broadcastreceiverproject;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button)findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("com.example.ldp.com..MY_BROADCAST");
sendBroadcast(intent);//发送标准广播
Log.d(MainActivity.ACTIVITY_SERVICE,"成功发送");
}
});
}
}
运行点击一下按钮是不是会接收到广播呢?那情况又来了,看看下面
新建MyBroadcastReceiverProject2
新建AnotherBroadcastReceiver广播类
package com.example.ldp.com.broadcastreceiverproject2;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class AnotherBroadcastReceiver 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,"sdsdsdsdsd",Toast.LENGTH_SHORT).show();
}
}
修改AndroidMainfest.xml文件,其实就跟上面一样的(口令)
<receiver
android:name=".AnotherBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.example.ldp.com..MY_BROADCAST"/>
</intent-filter>
</receiver>
再运行安装,回到上一个项目,点击按钮,是不是会出现两次提示消息呢,很明显这是两个程序两个apk文件才对
说明我们的标准广播是可以扩进程(前提是要有网络,个人认为)来接收广播的。这儿例子就证明了应用程序发出的广播是可以被其他应用程序接收到的。
发送有序广播
剩下的修改回到BroadcastReceiverProject中修改MainActivity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button)findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent("com.example.ldp.com..MY_BROADCAST");
/*sendBroadcast(intent);//发送标准广播*/
sendOrderedBroadcast(intent,null);//发送有序广播,第二个参数是和权限有关的
Log.d(MainActivity.ACTIVITY_SERVICE,"成功发送");
}
});
}
这个时候运行一下程序,发现两个程序仍然可以收到这条广播,这是咋回事儿啊?不是改成有序了嘛?
不过这个时候的广播器是有先后顺序,我们再AndroidMainfest.xml中修改它的优先级priority
<receiver
android:name=".MyBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter android:priority="100"> <!--设置为100保证在其他之前收到这个广播-->
<action android:name="com.example.ldp.com..MY_BROADCAST"/>
</intent-filter>
</receiver>
而且广播是可以 截断的,这样后面的应用都接收不到了,更保证了广播的 安全性(这个还是要靠本地广播,后面内容)。
修改MyBroadcastReceiver
package com.example.ldp.com.broadcastreceiverproject;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;
public class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// TODO: This method is called when the BroadcastReceiver is receiving
Toast.makeText(context,"AAAAA GetMyBroadcastReceiver",Toast.LENGTH_SHORT).show();
Log.d(MainActivity.ACTIVITY_SERVICE,"成功接收");
abortBroadcast();//截断广播
}
}
本地广播LocalBroadcastManager
运行一下就只有本程序能接收到广播了前面的广播都是垮进程的,对于保有数据的广播就有威胁了。所以引用本地广播LocalBroadcastManager,
这样只能在应用程序当中进行广播。步骤跟动态注册广播一样
效果图:
***ActivityCollector.finishAll()销毁所有的活动