安卓基础第七天(四大组件之BroadcastReceiver,样式主题,国际化,对话框)
2018-02-21 19:14
465 查看
BroadcastReceiver简介
Broadcast 是一种广泛运用的在应用程序之间传输信息的机制BroadcastReceiver 是对发送出来的Broadcast 进行过滤接受并响应的一类组件
简单创建BroadcastReceiver
接收SD卡移除时发送的广播1.新建一个SDCardUnmountedReceiver 类继承BroadcastReceiver 类当接收到匹配广播之后就会执行onReceive 方法
public class SDCardUnmountedReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Toast.makeText(context, "SDCard 已经被移除!", 0).show(); } }
2.注册SDCardUnmountedReceiver
注册一个广播接收者有两种方式。
静态注册:在AndroidManifest.xml 中注册广播清单文件中声明,需要在其中配置指定接收广播的动作(action),在AndroidManifest.xml 文件中添加如下配置:
<receiver android:name="com.itheima.broadcastReciver.SDCardUnmountedReceiver" > <intent-filter> <action android:name="android.intent.action.MEDIA_UNMOUNTED" /> <data android:scheme="file" > </data> </intent-filter> </receiver>
动态注册:在Java 代码中注册
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); IntentFilter intentFilter = new IntentFilter( "android.intent.action.MEDIA_UNMOUNTED"); intentFilter.addDataScheme("file"); registerReceiver(new SDCardUnmountedReceiver(), intentFilter); System.out.println("广播接收器已经注册成功。"); } }
两种注册的区别
代码注册:它不是常驻型广播,也就是说广播跟随程序的生命周期,一旦代码所在进程被杀死,广播接收者就失效
清单文件注册是常驻型,也就是说当应用程序关闭后,如果有信息广播来,程序也会被系统调用自动运行。一旦应用程序被部署到手机,广播接收者就会生效,高版本需要启动过一次才能接收到广播
PS:3.2 版本以上出于安全问题:从未启动过的广播接收程序,默认是接收不到广播的,必须有一个界面,然后通过界面启动一次这个程序。
生命周期
广播接收者也是运行在主线程中,所以在广播接收者的onReceive 方法内不能有耗时的操作,需要放在子线程中做但是onReceive 的生命周期很短,有可能广播接收者结束,子线程还没有结束,这时广播接收者所在进程很有可能被杀掉,这样子线程就会出问题
所以耗时操作最好放到service 服务中。
广播接收者的生命周期是非常短暂的,在接收到广播的时候创建,onReceive()方法结束之后销毁
Android中常见广播
短信监听
需要的权限<uses-permission android:name="android.permission.RECEIVE_SMS"/>
清单配置 PS:android 4.2 后废除了此action
<receiver android:name="com.itheima.smslistener.SmsListenerReceiver"> <intent-filter > <action android:name="android.provider.Telephony.SMS_RECEIVED" /> </intent-filter> </receiver>
代码
public class SmsListenerReceiver extends BroadcastReceiver { //当短信到来的时候执行 @Override public void onReceive(Context context, Intent intent) { //获取发送者的号码 和发送内容 Object []objects = (Object[]) intent.getExtras().get("pdus"); for (Object obj : objects) { //[1]获取smsmessage实例 SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) obj); //[2]获取发送短信的内容 String messageBody = smsMessage.getMessageBody(); String address = smsMessage.getOriginatingAddress(); System.out.println("body:"+messageBody+"-----"+address); } } }
监听系统开机
拦截的广播<action android:name="android.intent.action.BOOT_COMPLETED"></action>
需要的权限
PS:3.2 以上版本必须加权限,,3.2 以上的版本如果用户没有启动过程序, 接收不到开启启动完成的广播
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
代码
java.lang.RuntimeException: Unable to start receiver com.itheima.bootreceiver.BootReceiver: android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
public class BootReceiver extends BroadcastReceiver { //当手机重新启动的时候调用 @Override public void onReceive(Context context, Intent intent) { //在这个方法里面开启activity Intent intent2 = new Intent(context,MainActivity.class); //☆☆☆注意 不能在广播接收者里面直接开启activity 需要添加一个标记 添加一个任务栈的标记 intent2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); //开启activity context.startActivity(intent2); } }
监听卸载安装
拦截的广播<action android:name="android.intent.action.PACKAGE_ADDED"></action>
<action android:name="android.intent.action.PACKAGE_REMOVED"></action>
需要指定scheme: package
<data android:scheme="package"/>
代码
public class AppStateReceiver extends BroadcastReceiver { //当有新的应用被安装 了 或者有应用被卸载 了 这个方法调用 @Override public void onReceive(Context context, Intent intent) { //获取当前广播事件类型 String action = intent.getAction(); //PACKAGE_INSTALL为预留无效action if ("android.intent.action.PACKAGE_INSTALL".equals(action)) { System.out.println("应用安装了11111"); }else if ("android.intent.action.PACKAGE_ADDED".equals(action)) { System.out.println("应用安装了22222"); }else if("android.intent.action.PACKAGE_REMOVED".equals(action)){ System.out.println("应用卸载了"+intent.getData()); } } }
监听打电话
拦截的广播:<action android:name="android.intent.action.NEW_OUTGOING_CALL"></action>
需要的权限:
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
特殊广播的接收者
比如操作特别频繁的广播事件 ,屏幕的锁屏和解锁, 电池电量的变化这样的广播接收者在清单文件里面注册无效
报错
Activity com.itheima.screen.MainActivity has leaked IntentReceiver com.itheima.screen.ScreenReceiver@b6486088 that was originally registered here. Are you missing a call to unregisterReceiver()?
发送自定义广播
无序广播
符号某广播条件的所有广播接收者的特点,无序,无优先级,不可中断,接收者不可传递数据BroadcastReceiver trying to return result during a non-ordered broadcast
无序广播使用sendBroadcast 方法来发送
广播时可设置接收者权限,仅当接收者含有权限才能接收
接收者的也可设置发送方权限,只接收含有权限应用的广播
Receiver 节点增加属性permission
发送广播时,通过intent.setFlags(intent.flag_include_stopped_pakeages),包含从
未启动过的程序,这样设置,可以让从未启动的接收者也收到广播
//点击按钮 发送一条无序广播 public void click(View v) { Intent intent = new Intent(); intent.setAction("com.itheima.custom"); intent.putExtra("name", "新闻联播每天晚上 7点准时开整!!"); sendBroadcast(intent);//发送无序广播 }
有序广播
有序广播使用sendOrderedBroadcast 方法来发送接收者可以在中定义android:priority 定义优先级,数字越大优先级越高,官方定义范围是:
1000(最高) ~ -1000(最低),系统默认优先级是0
有序广播可以被拦截或添加数据,优先级高的接收者可以拦截优先级低的
使用abortBroadcast 方法拦截,setResultExtras(Bundle)传递数据
代码
发送有序广播
sendOrderedBroadcast(intent, null, new FinalReceiver(), null, 1, "习大大给每个村民发了1000斤大米", null);
接收者
public class ProvienceReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { //[1]获取发送广播携带的数据 String content= getResultData(); //[2]显示结果 Toast.makeText(context, "省:"+content, 1).show(); //[2.1]终止广播 abortBroadcast(); //[3]修改数据 setResultData("习大大给每个村民发了500斤大"); } }
最终接收者,被拦截的广播依然可以接收到,无需注册
public class FinalReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { //[1]获取发送广播携带的数据 String content= getResultData(); //[2]显示结果 Toast.makeText(context, "报告习大大:"+content, 1).show(); } }
样式主题
样式
Android Style 类似网页设计中的级联样式CSS 设计思路,可以让设计与内容分离,并且可以方便的继承、覆盖、重用同CSS 一样,样式的引入遵循就近原则,在控件上定义的属性会覆盖被引入的样式中的同一个属性
在工程中res->values->styles.xml 文件定义样式
<style name="btn_style"> <item name="android:layout_height">wrap_content</item> <item name="android:layout_width">wrap_content</item> <item name="android:textSize">20sp</item> <item name="android:textColor">#ff0000</item> <item name="android:text">自定义样式</item> </style> <!-- 继承上一个样式,相同的属性则覆盖父类 --> <style name="btn_style_child" parent="btn_style"> <item name="android:textColor">#0000ff</item> </style>
使用个style=”@style/btn_style”属性添加样式
主题
主题的定义与样式的定义相同,都是定义在styles.xml 文件下不同之处在于主题是作用在Activity 上的
主题通过定义AndroidManifest.xml 文件中的和节点下的”android:theme”属性作用在整个应用或者某个Activity
当主题和样式属性发生冲突时,样式的优先级高于主题
透明主题:@android:style/Theme.Translucent
reference–>android–>R.style 中查看文档
国际化
Internationalization太长也简称为I18NAndroid 可以通过资源文件非常方便的实现程序的国际化。
res/目录下
1.创建名称为values-zh-rCN、values-zh-rTW 和values-en-rUS的文件夹
2.然后在每个文件夹中创建一个对应的strings.xml 文件,并在该文件中定义对应语言的字符串即可
3.图片也可以进行国际化,创建名称类似drawable-zh-rCN,drawable-zh-rTW 这样的文件夹,将图片资源存放在文件夹下即可
帧动画
Drawable Animation(Frame Animation):帧动画,就像GIF 图片,通过一系列Drawable 依次显示来模拟动画的效果。Android 中的常见对话框
Android 中常用的对话框有:通知对话框、列表对话框、单选对话框、多选对话框以及进度对话框。
通知对话框、列表对话框、单选以及多选对话框由AlertDialog.Builder创建
进度对话框由ProgressDialog 创建。
代码
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } //点击按钮 弹出一个普通对话框 public void click1(View v){ //通过builder 构建器来构造 AlertDialog.Builder builder = new Builder(this); builder.setTitle("警告"); builder.setMessage("世界上最遥远的距离是没有网络 "); builder.setPositiveButton("确定", new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { System.out.println("点击了确定按钮"); } }); builder.setNegativeButton("取消", new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { System.out.println("点击了取消按钮 "); } }); //最后一步 一定要记得 和Toast 一样 show出来 builder.show(); } //点击按钮 弹出一个单选对话框 public void click2(View v){ //通过builder 构建器来构造 AlertDialog.Builder builder = new Builder(this); builder.setTitle("请选择您喜欢的课程"); final String items[] = {"Android","ios","c","C++","html","C#"}; //-1代表没有条目被选中 builder.setSingleChoiceItems(items, -1, new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { //[1]把选择的条目给取出来 String item = items[which]; Toast.makeText(getApplicationContext(), item, 1).show(); //[2]把对话框关闭 dialog.dismiss(); } }); //最后一步 一定要记得 和Toast 一样 show出来 builder.show(); } //点击按钮 弹出一个对选对话框 public void click3(View v){ //通过builder 构建器来构造 AlertDialog.Builder builder = new Builder(this); builder.setTitle("请选择您喜欢吃的水果"); final String items[] = {"香蕉","黄瓜","哈密瓜","西瓜","梨","柚子","榴莲"}; final boolean[] checkedItems={true,false,false,false,false,false,true}; builder.setMultiChoiceItems(items, checkedItems, new OnMultiChoiceClickListener() { @Override public void onClick(DialogInterface dialog, int which, boolean isChecked) { } }); builder.setPositiveButton("确定", new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { //把选中的 条目的数据给我取出来 StringBuffer sb = new StringBuffer(); for (int i = 0; i < checkedItems.length; i++) { //判断一下 选中的 if (checkedItems[i]) { String fruit = items[i]; sb.append(fruit + " "); } } Toast.makeText(getApplicationContext(), sb.toString(), 1).show(); //关闭对话框 dialog.dismiss(); } }); //最后一步 一定要记得 和Toast 一样 show出来 builder.show(); } //点击按钮 弹出一个进度条对话框 public void click4(View v){ final ProgressDialog dialog = new ProgressDialog(this); dialog.setTitle("正在玩命加载ing"); //设置一下进度条的样式 dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); //最后一步一定要记得show 出来 dialog.show(); //创建一个子线程 new Thread(){public void run() { //设置进度条最大值 dialog.setMax(100); //设置当前进度 for (int i = 0; i <=100 ; i++) { dialog.setProgress(i); //睡眠一会 SystemClock.sleep(50); } //关闭对话框 dialog.dismiss(); };}.start(); } }
activity.this与getApplicationContext()区别
一般情况:可以用activity.this.代替getApplicationContext()activity,弹出对话框时,生命周期方法:onpause()、onResume()方法不会执行因为对话框是activity 的一部分。
所以:构造对话框的Builder(context),这个context 是指定这个对话框挂载在哪个activity 上只能是activity.this获取的是子类的activity,当前activity context
不能是getApplicationContext(),整个应用程序的上下文
因为getApplicationContext 获取的是父类的activity而子类有的东西,父类不一定有。
相关文章推荐
- 0908Android基础四大组件之BroadcastReceiver
- 安卓四大组件之广播(BroadCastReceiver)
- Android核心基础-9.Android四大组件之BroadcastReceiver
- Android基础学习【历史流程重走】 ----四大组件之BroadCastReceiver
- Android 第七天重置版_样式主题国际化动画对话框
- 安卓四大组件之BroadcastReceiver
- 【Android基础】(3)四大核心组件之BroadcastReceiver
- 四大组件之BroadcastReceiver 基础
- 【Android基础入门〖5〗】四大组件之BroadcastReceiver
- Android四大组件之广播接收者(BroadcastReceiver)
- Android四大组件之BroadcastReceiver
- Android四大组件之一:BroadcastReceiver(广播接收者)
- 安卓入门--四大组件--BroadcastRecivier
- Android四大基本组件之一 ,广播(broadcast receiver)---无序广播
- 四大组件之 BroadcastReceiver小结
- android学习笔记(三)四大组件Broadcast Receiver详解
- Android四大组件之BroadcastReceiver
- 浅谈Android四大组件之BroadcastReceiver
- Android第二讲——Intent、四大组件(Activity、BroadcastReceiver、ContentProvider、Service(IntentService))
- 四大组件之BroadcastReceiver