目录标题
广播分类
- 标准广播
完全异步执行, 接收器同时接收,广播不可截断 - 有序广播
同步执行,发出后只有一个接收器能接收,结束才能继续往下走,广播可截断
接收系统广播
- 动态注册监听网络变化
- 创建广播接收器:
- 新建类,继承BroadcastReceiver,重写onReceive()
- 通过调用onDestory中的unregisterReceiver()方法实现取消注册
//声明系统访问权限
<uses-permission android:name="android:permission.ACCESS_NETWORK_STATE" />
public class BootCompleteReceiver{
public coid onReceiver(Context context,Intent intent){
Toast.makeText(context,"Boot Complete",Toast.LENGTH_SHORT).show();
}
}
- 静态注册 程序未启动就能接受到广播
- 快捷创广播接收器
点击创建的项目包 com.example.broadcast
new -> Other -> Broadcast Receiver
勾选 - 在ActivityManifest.xml中注册
- 自由控制注册与注销
- 广播接收器中不允许开多线程,添加过多逻辑十分耗时,因此只常借此来 打开程序其他组件
- 快捷创广播接收器
Exported:是否允许这个广播接收器接收本程序以外的广播
Enabled:是否启用这个广播接收器
android:name指定具体注册哪一个广播接收器
uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED
<Intent>
<action android:name="android.intent.action.BOOT_COMPLETED">
</Intent>
发送自定义广播
public class MainActivity extends AppCompatActivity {
private IntentFilter intentFilter;
private NetworkChangeReceiver networkChangeReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intentFilter =new IntentFilter();//创建实例
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
//当网络状态发生变化时,发出来的正是“值为android.net.conn.CONNECTIVITY_CHANGE的广播
//想要监听什么样的广播,就在这里添加相应的action
networkChangeReceiver=new NetworkChangeReceiver();
registerReceiver(networkChangeReceiver,intentFilter);
//创建实例,注册,实现监听网络变化的功能
}
protected void onDestory(){
super.onDestroy();
unregisterReceiver(networkChangeReceiver);
//unregister,动态广播接收器最后要取消注册
}
class NetworkChangeReceiver extends BroadcastReceiver{
//内部类--创建一个接收器,继承BroadcastReceiver,重写onReceiver
public void onReceive(Context context, Intent intent){
//当网络状态变化时,它就会执行
//Toast.makeText(context,"network changes",Toast.LENGTH_SHORT).show();//show方法
ConnectivityManager connectionManager=(ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
//系统服务类得到ConnectivityManager的实例,专门管理网络连接
// getActivityNetworkInfo拿到NetworkInfo实例,使用isavailable()方法
NetworkInfo networkInfo=connectionManager.getActiveNetworkInfo();
if(networkInfo!=null&&networkInfo.isAvailable()){
Toast.makeText(context,"network is available",Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(context,"network is unavailable",Toast.LENGTH_SHORT).show();
}
}
}
}
- 发送标准广播
- 当MyBroadcastReceiver收到自定义广播时,会弹出"received in MyBraodcastReceiver",此时在ActivityManifest.xml中修改:
<Intent-fliter>
<action android:name="com.example.broadcast.MY_BROADCAST">
</Intent_fliter>
- 在布局中定义一个按钮 button
- 在MainActivity:
setContentView...
//修改:
Button button=(Button)findViewById(R.id.Button)
button.setOnClickListener(new View onClickListener){//
public void onClick(View v){
Intent intent=new Intent ("com.exampleBroadcast.My_BROADCAST");
//构建intent对象,传入要发送的广播值
sendBroadCast(intent)
//将广播发送出去,监听com.example.broadcasttest.MY_broadcast就会收到消息
}
}
- 发送有序广播
Intent intent=new Intent("com.example.broadcasttest,MY_BROADCAST");
sendOrderedBroadcast(intent,null);//第二个参数:与权限相关的字符串,传入null即可
设定先后顺序 android:priority
<Intent-fliter android:priority="100">
<action android:name="com.example.nroadcasttest.MY_BROADCAST"/>
截断广播 abortBroadcast()
public class MyBroadcastReceiver extends BroadcastReceiver{
public void onReceive(Context context,Intent intent){
Toast.makeText(context,"received in MyBroadcastReceiver",Toast.LENGTH_SHORT).show();
abortBroadcast();
}
}
使用本地
LocalBroadcastManager 管理广播 getInstance获取实例 sendBroadcast(intent) 发送本地广播
- 特点:
- 应用程序的传递 和 接收器的接收 都只限定在本地
- 更安全,更高效
- 因为本地广播运行时程序已经启动,故无法通过静态注册来发送本地广播
public class MainActivity extends AppCompatActivity{
private IntentFilter intentFilter;
private LocalReceiver localReceiver;//定义LocalReceiver对象
private LocalBroadcastManager localBroadcastManager;//定义LocalBroadcastManager对象
protected void onCreate(Bundle saveInstanceState){
super.onCreate(saveInstanceState);
setContentView(R.layout.activity_main);
localBroadcastManager=LocalBroadcastManager.getInstance(this);//获取实例
Button button=(Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener(){
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);//(un)registerReceiver注销/注册本地广播监听器
}
protected void onDestory(){
super.onDestroy();
localBroadcastManager.unregisterReceiver(localReceiver);//注销
}
class LoaclReceiver extends BroadcastReceiver{
public void onReceive(Context context,Intent intent){
Toast.makeText(context,"received local broadcast",Toast.LENGTH_LONG).show();
}
}
强制下线
构建对话框 AlterDialog.Builder
对话框不可取消 setCancelable()
给对话框注册确定按钮 setPositiveButton()
销毁所有活动 重新启动LoginActivity: finishAll()
onResume() onPause() 当一个活动失去栈顶位置时就会自动取消广播接收器的注册注册和注销 ForceOfflineReceiver()
ActivityManifest.xml
如果报Apps targeting Android 12 and higher are required to specify an explicit value for android:exported
when the corresponding component has an intent filter defined. 在LoginActivity后面补上 android:exported="true"
//将LoginActivity改为主活动
<activity android:name=".MainActivity">
</activity>
<activity android name=".LoginActivity">
<Intent-filter>...
activity_login.xml
orientation 是 horizonal,不然会将密码栏和login按钮遮住
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="60dp" >
<TextView
android:layout_width="90dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:textSize="18sp"
android:text="Account:" />
<EditText
android:id="@+id/account"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="center_vertical"/>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="60dp">
<TextView
android:layout_width="90dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:textSize="18sp"
android:text="Password:" />
<EditText
android:id="@+id/password"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="center_vertical"
android:inputType="textPassword"/>
</LinearLayout>
<Button
android:id="@+id/login"
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="Login"/>
</LinearLayout>
activity_main.xml
<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/force_offline"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Send force offline broadcast" />
</LinearLayout>
ActivityCollector 管理活动
public static List<Activity> activities =new ArrayList<>();
public static void addActivity(Activity activity){
activities.add(activity);
}
public static void removeActivity(Activity activity){
activities.remove(activity);
}
public static void finishAll(){
for(Activity activity:activities){
if(!activity.isFinishing()){
activity.finish();
}
}
}
BaseActivity 所有活动的父类
public class BaseActivity extends AppCompatActivity {
private ForceOfflineReceiver receiver;
@Override
protected void onCreate( Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityCollector.addActivity(this);
}
@Override
protected void onResume() {
super.onResume();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("com.example.broadcastbestpractice.FORCE_OFFLINE");
receiver = new ForceOfflineReceiver();
registerReceiver(receiver,intentFilter);
}
@Override
protected void onPause() {
super.onPause();
if(receiver != null){
unregisterReceiver(receiver);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
ActivityCollector.removeActivity(this);
}
private class ForceOfflineReceiver extends BroadcastReceiver {
@Override
public void onReceive(final Context context, Intent intent) {
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 dialogInterface, int i) {
ActivityCollector.finishAll(); //销毁所有活动
Intent intent = new Intent(context,LoginActivity.class);
context.startActivity(intent); //重新启动LoginActivity
}
});
builder.show();
}
}
}
MainActivity
public class MainActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button forceOffline = (Button) findViewById(R.id.force_offline);
forceOffline.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent("com.example.broadcastbestpractice.FORCE_OFFLINE");
sendBroadcast(intent);
}
});
}
}
LoginActivity
public class LoginActivity extends AppCompatActivity {
private EditText accountEdit;
private EditText passwordEdit;
private Button login;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login2);
accountEdit=(EditText)findViewById(R.id.account);
passwordEdit=(EditText)findViewById(R.id.password);//获取密码,账号实例
login=(Button)findViewById(R.id.login);
login.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
String account = accountEdit.getText().toString();
String password = passwordEdit.getText().toString();
if (account.equals("Alice") && password.equals("12345678")) {
Intent intent = new Intent(LoginActivity.this, MainActivity.class);//Intent,登录成功,就跳转到MainActivity
startActivity(intent);
finish();
} else {
Toast.makeText(LoginActivity.this, "account or password is invalid", Toast.LENGTH_SHORT).show();
}
}
});
}
}
过程中特别撒币的把类建到了不同的包下面,导致出现了下面的提示:MainActivity must extend android.app.Activity
各位伙伴要是也出现了相同的情况,注意检查一下哟~
Git
-
Git 下载与安装
当时下载了很多次都是失败,最后通过 复制链接 的方式下载才成功,安装很多都是默认项,next挺容易 -
建代码仓库
cd d: 项目在哪个盘,就写 cd 几:,如果报 No found file or directory 注意检查一下自己的路径,是不是项目所在路径,空格冒号输入时都要注意
-
add
把想要提交的代码添加进来 -
commit
提交
git add build.gradle //添加 build.gradle 文件
git add app = git add. //添加 app目录
git commit -m "First commit." // -m加上提交描述的信息