day07
1 为什么需要广播接收
[1]有什么样的人员听广播
[2]想听广播必须有电台
[3]Android系统内部已经定义好了电台 已经定义好了一些广播事件 比如 外拨电话 短信到来 sd卡状态 电池电量....
[4]使用broadcastReceiver去接收系统已经定义好的这些事件
[5]定义广播接收者的目的是为了方便开发者进行开发
2 广播接收者案例-ip拨号器 17951 024-8856789
[1]定义广播接收者
[2]在清单文件里配置
[3]具体调到某一个合适的频道
[4]记得加权限
3 广播接收者案例-sd卡状态监听
[1]定义广播接收者
package com.phone.sdcardstatusspy;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class SdcardStateReceiver extends BroadcastReceiver {
//当sd状态发送改变的时候执行
@Override
public void onReceive(Context context, Intent intent) {
//获取当前广播的事件类型
String action = intent.getAction();
if("android.intent.action.MEDIA_MOUNTED".equals(action)){
System.out.print("说明SD卡挂载了...");
}else if("android.intent.action.MEDIA_UNMOUNTED".equals(action)){
System.out.print("说明SD卡卸载了...");
}
}
}
[2]在清单文件里配置
<receiver android:name="com.phone.sdcardstatusspy.SdcardStateReceiver">
<intent-filter >
<action android:name="android.intent.action.MEDIA_MOUNTED"/>
<action android:name="android.intent.action.MEDIA_UNMOUNTED"/>
<!-- 小细节 这里需要配置一个data 约束类型叫file 因为sd里面存的数据类型是file -->
<data android:scheme="file"/>
</intent-filter>
</receiver>
4 广播接收者案例-短信监听器
[1]定义广播接收者
package com.phone.smslistener;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.SmsMessage;
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);
}
}
}
[2]在清单文件里配置
<receiver android:name="com.phone.smslistener.SmsListenerReceiver">
<intent-filter >
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
[3]加权限
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
5 不同版本广播的特点
[1]在4.0 谷歌工程师要求 第一次安装应用的时候必须的有界面 这样广播接收者才生效
[2]在设置页面有一个强行停止的按钮 如果说用户点击了 强行停止按钮那么广播接收者也不生效
[3]在2.3的手机上没有这样的安全设计
6 广播接收者案例-卸载安装
[1]定义广播接收者
package com.phone.appstate;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class AppStateReceiver extends BroadcastReceiver {
//当有新的应用被安装了 或者有应用被卸载了 这个方法被调用
@Override
public void onReceive(Context context, Intent intent) {
//获取当前广播的事件类型
String action = intent.getAction();
if("android.intent.action.PACKAGE_INSTALL".equals(action)){
System.out.println("应用安装了1111");
}else if("android.intent.action.PACKAGE_REMOVED".equals(action)){
System.out.println("应用卸载了");
}else if("android.intent.action.PACKAGE_ADDED".equals(action)){
System.out.println("应用安装了2222");
}
}
}
[2]在清单文件里配置
<receiver android:name="com.phone.appstate.AppStateReceiver">
<intent-filter >
<action android:name="android.intent.action.PACKAGE_INSTALL"/>
<action android:name="android.intent.action.PACKAGE_REMOVED"/>
<action android:name="android.intent.action.PACKAGE_ADDED"/>
<!-- 小细节 需要配置一个data -->
<data android:scheme="package"/>
</intent-filter>
</receiver>
7 广播接收者案例-开机启动
注意:不能直接在广播接收者中开启activity
[1]定义广播接收者
package com.phone.reboot;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
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);
}
}
[2]在清单文件里配置
<receiver android:name="com.phone.reboot.BootReceiver">
<intent-filter >
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
[3]加权限
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
8 有序广播和无序广播
[1]有序广播 类似中央发送红头文件 按照一定的优先级接收
<1>发送有序广播
//点击按钮 发送有序广播 发大米
public void click(View v){
Intent intent = new Intent();
intent.setAction("com.phone.sendrice");
/**
* intent 意图
* receiverPermission 接收的权限
* resultReceiver 最终的receiver
* scheduler handler
* initialCode 初始码
* initialData 初始化数据
* initialExtras 发送数据
*/
sendOrderedBroadcast(intent, null, new FinalReceiver(), null, 1, "习总给每个村民发了1000斤大米", null);
}
<2>接收有序广播
package com.phone.receiverice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class ProvinceReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//[1]获取发送广播携带的数据
String content = getResultData();
//[2]显示结果
Toast.makeText(context, "省"+content, 1).show();
//终止广播
//abortBroadcast();
//[3]修改数据
setResultData("习总给每个村民发了500斤大米");
}
}
package com.phone.receiverice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class CityReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// [1]获取发送广播携带的数据
String content = getResultData();
// [2]显示结果
Toast.makeText(context, "市" + content, 1).show();
//[3]修改数据
setResultData("习总给每个村民发了250斤大米");
}
}
package com.phone.receiverice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class CountryReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// [1]获取发送广播携带的数据
String content = getResultData();
// [2]显示结果
Toast.makeText(context, "乡" + content, 1).show();
//[3]修改数据
setResultData("习总给每个村民发了125斤大米");
}
}
package com.phone.receiverice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class FarmerReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// [1]获取发送广播携带的数据
String content = getResultData();
// [2]显示结果
Toast.makeText(context, "农民" + content, 1).show();
}
}
<3>配置清单文件
<!-- 配置省长receiver 优先级最高 -->
<receiver android:name="com.phone.receiverice.ProvinceReceiver">
<intent-filter android:priority="1000">
<action android:name="com.phone.sendrice"/>
</intent-filter>
</receiver>
<!-- 配置市长receiver 优先级最高 -->
<receiver android:name="com.phone.receiverice.CityReceiver">
<intent-filter android:priority="100">
<action android:name="com.phone.sendrice"/>
</intent-filter>
</receiver>
<!-- 配置乡长receiver 优先级最高 -->
<receiver android:name="com.phone.receiverice.CountryReceiver">
<intent-filter android:priority="10">
<action android:name="com.phone.sendrice"/>
</intent-filter>
</receiver>
<!-- 配置农民receiver 优先级最高 -->
<receiver android:name="com.phone.receiverice.FarmerReceiver">
<intent-filter android:priority="1">
<action android:name="com.phone.sendrice"/>
</intent-filter>
</receiver>
[2]无序广播 比如新闻联播 每天晚上7点准时开播
//点击按钮 发送一条无序广播
public void click(View v){
Intent intent = new Intent();
intent.setAction("com.phone.custom");
intent.putExtra("name", "新闻联播每天晚上7点准时开播");
//发送无序广播
sendBroadcast(intent);
}
package com.phone.getchaos;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class ReceiveCustomReceiver extends BroadcastReceiver {
//当接收到我们发送的自定义广播
@Override
public void onReceive(Context context, Intent intent) {
//[1]获取接收发送的数据
String content = intent.getStringExtra("name");
//[2]展示内容
Toast.makeText(context, content, 1).show();
}
}
总结: (1)有序广播可以被终止
(2)有序广播的数据可以被修改
(3)无序广播不可以被终止
(4)数据不可以被修改
9 特殊广播接收者
操作特别频繁的广播事件 比如 屏幕的锁屏和解锁 电池电量的变化 这种事件的广播在清单文件里注册是无效的
手机解锁屏:
package com.phone.screen;
import android.support.v7.app.ActionBarActivity;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
public class MainActivity extends ActionBarActivity {
private ScreenReceiver screenReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
screenReceiver = new ScreenReceiver();
// <receiver android:name="com.phone.screen.ScreenReceiver">
// <intent-filter >
// <action android:name="android.intent.action.SCREEN_OFF"/>
// <action android:name="android.intent.action.SCREEN_ON"/>
// </intent-filter>
// </receiver>
//创建IntentFilter对象
IntentFilter filter = new IntentFilter();
//添加要注册的action
filter.addAction("android.intent.action.SCREEN_OFF");
filter.addAction("android.intent.action.SCREEN_ON");
registerReceiver(screenReceiver, filter);
}
@Override
protected void onDestroy() {
//当activity销毁的时候要取消广播接收者
unregisterReceiver(screenReceiver);
super.onDestroy();
}
}
package com.phone.screen;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class ScreenReceiver extends BroadcastReceiver {
//当我们进行屏幕锁屏和解锁 这个方法执行
@Override
public void onReceive(Context context, Intent intent) {
//获取当前广播的事件类型
String action = intent.getAction();
if("android.intent.action.SCREEN_OFF".equals(action)){
System.out.println("屏幕锁屏了");
}else if("android.intent.action.SCREEN_ON".equals(action)){
System.out.println("屏幕解屏了");
}
}
}
注册广播接收者的2种方式
[1]动态注册 通过代码方式注册
[2]在清单文件通过receiver tag节点静态发布
10 样式和主题
样式一般作用在控件上(button,textview等) 样式作用范围比较窄
主题一般作用在activity或者Application结点下 样式作用范围比较宽
11 国际化(i18n)
在res下创建不同国家语言环境集目录 目录的固定写法values- en(或者其他,这里是每种语言的标号)
12 常见对话框
Toast
Toast.makeText(getApplicationContext(), item, 1).show();
普通对话框
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("正在玩命加载中...");
//设置一下进度条的样式
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
//最后一步一定要记得show()
dialog.show();
//创建一个子线程
//与进度有关的,可以在子线程更新UI
new Thread(){
public void run(){
//设置进度条的最大值
dialog.setMax(100);
//设置当前进度
for(int i = 0; i <= 100; i++){
dialog.setProgress(i);
//睡眠一会
SystemClock.sleep(50);
}
//关闭对话框
dialog.dismiss();
}
}.start();
}
13 2种上下文的区别 (在对话框的情况下用第一种)
[1]this 最终继承Context
[2]getApplicationContext() 返回的对象是Context
14 Android中动画
[1]帧动画
加载一系列的图片
<1>在res目录下创建drawable目录,并创建xml文件和放入一系列 的图片
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false" >
<item
android:drawable=""
android:duration="200">
</item>
<item
android:drawable=""
android:duration="200">
</item>
<item
android:drawable=""
android:duration="200">
</item>
<item
android:drawable=""
android:duration="200">
</item>
<item
android:drawable=""
android:duration="200">
</item>
<item
android:drawable=""
android:duration="200">
</item>
</animation-list>
<2>设置
package com.phone.drawableanimate;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.os.SystemClock;
import android.app.Activity;
import android.widget.ImageView;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//[1]找到控件
final ImageView rocketImage = (ImageView) findViewById(R.id.iv);
//[2]设置背景资源
rocketImage.setBackgroundResource(R.drawable.my_anim);
//兼容低版本的写法
new Thread(){public void run() {
SystemClock.sleep(20);
//[3]获取AnimationDrawable类型
AnimationDrawable rocketAnimation = (AnimationDrawable) rocketImage.getBackground();
//[4]开启动画
rocketAnimation.start();
};}.start();
}
}
[2]View动画 补间动画
[3]属性动画
只言片语任我说,提笔句句无需忖。落笔不知寄何人,唯有邀友共斟酌。