[安卓基础]学习第七天

一、为什么需要广播接收者(broadcastReceiver)

1.有什么样的人员听广播 老人,出租车司机
2.听广播必须:电台,收音机,调频道
3.Android内部已经定义好了电台,已经定义好了一些广播事件,如外拨电话,短信到来等等
4.使用broadcastReceiver去接收系统定义好的这些事件
5.javame javase javaee
6.定义广播接收者目的是为了方便安卓开发者开发

二、案例

2-1.案例——ip拨号器

360永久免费 瑞星 卡巴斯基

1.在清单文件中配置receiver,并添加用户权限

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

<application
    //......
    <!-- 配置广播接收者 -->
    <receiver android:name="com.elnui.day07_caseip.OutGoingCallReceiver">
        <intent-filter>
            <action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
        </intent-filter>
    </receiver>
</application>

2.新建一个类继承BroadcastReceiver

public class OutGoingCallReceiver extends BroadcastReceiver{

    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO Auto-generated method stub

        // 获取用户输入的ip号码在config.xml文件中
        SharedPreferences sp = context.getSharedPreferences("config", 0);
        String number = sp.getString("ipnumber", "");

        // 获取当前拨打的电话
        String num = getResultData();

        // 在当前号码前假17951
        // 判断当前号码是不是长途号码
        if(num.startsWith("0")){
            // 修改拨打的号码
            setResultData(number + num);
        }
    }
}

3.getResultData()

Retrieve the current result data, as set by the previous receiver. Often this is null.

4.setResultData()

Change the current result data of this broadcast; 
only works with broadcasts sent through Context.sendOrderedBroadcast. 
This is an arbitrary string whose interpretation is up to the broadcaster. 

5.总结

  • BroadcastReceiver是一个抽象类,没有上下文
public abstract class BroadcastReceiver{}
  • public void onReceive(Context context, Intent intent) {},该方法中的context就是上下文

2-2.案例——sd卡监听器

1.onReceive()方法

- intent.getAction();    //获取当前广播的事件类型 
    Retrieve the general action to be performed, such as ACTION_VIEW. 
    The action describes the general way the rest of the information in the intent should be interpreted
        -- most importantly, what to do with the data returned by getData.

2.清单文件配置

<receiver android:name="com.elnui.day07_casesd.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>
说明:<intent-filter>下必须添加<data android:scheme="file"/>

3.代码

public class SdcardStateReceiver extends BroadcastReceiver{

    // 当SD卡状态发生改变时调用
    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO Auto-generated method stub
        String action = intent.getAction();
        if("android.intent.action.MEDIA_MOUNTED".equals(action)){
            System.out.println("SD卡挂载了。");
        }else if("android.intent.action.MEDIA_UNMOUNTED".equals(action)){
            System.out.println("SD卡挂载了。");
        }
    }
}

2-3.案例——短信监听器

1.代码

public class SmsListerReceiver extends BroadcastReceiver {

    // 当短信到来的时候执行
    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO Auto-generated method stub
        System.out.println("Receive sms.............success!!!");

        // 获取发送者的号码和内容
        Object []objects = (Object[]) intent.getExtras().get("pdus");
        for (Object obj : objects) {
            // 获取SmsMessage的实例
            SmsMessage smg = SmsMessage.createFromPdu((byte[])obj);

            String messageBody = smg.getMessageBody();
            String messageAddr = smg.getOriginatingAddress();
            System.out.println("___Address:" + messageAddr + ":" + messageBody);
        }
    }
}

2.清单文件配置

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

<receiver android:name="com.elnui.day07_casesms.SmsListerReceiver">
    <intent-filter>
        <action android:name="android.provider.Telephony.SMS_RECEIVED" />
    </intent-filter>
</receiver>

3.类SmsManager

  • pdu也是封装短信的一种格式

4.类SmsMessage (android.telephony包下)

通过这个API拿到短信的信息
通过静态的createFromPdu()即可获得实例

- getOriginatingAddress(); // 获取号码
- getMessageBody(); // 获取内容

2-4.卸载安装

1.代码

public class StatusReceiver 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("___PACKAGE_INSTALL");
        }else if("android.intent.action.PACKAGE_REMOVED".equals(action)){
            System.out.println("___PACKAGE_REMOVED");
        }else if("android.intent.action.PACKAGE_ADDED".equals(action)){
            System.out.println("___PACKAGE_ADDED" + intent.getData());
        }
    }
}

2.清单文件配置(此处得配置data)

<receiver android:name="com.elnui.day07_caseinstall.StatusReceiver">
    <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>
android.intent.action.PACKAGE_INSTALL是谷歌工程师预留的字符段

3.getData()

intent.getData()可以拿到包名

2-5.开机启动

1.代码

public class BootReceiver extends BroadcastReceiver {

    // 当手机重启时调用
    @Override
    public void onReceive(Context context, Intent intent) {

        // 开启Activity
        Intent x  = new Intent(context,MainActivity.class);

        // 添加标记
        x.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        context.startActivity(x);
    }
}

2.清单文件配置

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<application>
    <receiver android:name="com.elnui.day07_reboot.BootReceiver">
        <intent-filter >
            <action android:name="android.intent.action.BOOT_COMPLETED"/>
        </intent-filter>
    </receiver>
</application>

3.注意

不能在广播接收者里面开启Activity,需要添加一个任务栈的标记
开机启动一定要加RECEIVE_BOOT_COMPLETED权限
// 添加标记
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

4.补充

在页面按返回键会调用onBackPressed()
    @Override
    public void onBackPressed() {
        // TODO Auto-generated method stub
        super.onBackPressed();
    }

三、不同版本广播的特点

四、有序广播和无序广播

4-1.无序广播

比如新闻联播,到7点就播

1.广播发送者

代码
    public void click1(View v){
        Intent intent = new Intent();
        intent.setAction("com.elnui.custom");
        intent.putExtra("name", "准时开播");
        sendBroadcast(intent);
    }

2.广播接收者

代码
public class wuxuRecelver extends BroadcastReceiver {

    // 当接收到自定义的广播时执行
    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO Auto-generated method stub
        String str = intent.getStringExtra("name");

        Toast.makeText(context, str, 1).show();
    }
}
清单文件
        <receiver android:name="com.elnui.day07_recelve.wuxuRecelver">
            <intent-filter >
                <action android:name="com.elnui.custom"/>
            </intent-filter>
        </receiver>

4-2.有序广播

类似中央发送红头文件,按照优先级进行接收

1.发送者

代码
    // 点击发送有序广播
    public void click1(View v){
        Intent intent = new Intent();
        intent.setAction("com.elnui.sendOrderBroadcast");

        /**
         * intent 意图
         * receiverPermission 接收的权限
         * resultReceiver 最终的recriver
         * scheduler handler
         * initialCode 初始码
         * initialData 初始化数据
         * initialExtras 额外数据
         * 
         * */
        sendOrderedBroadcast(intent, null, new FinalReceiver(), null, 1, "有序广播-1000", null);
    }

2.接收者(以其中一个为例)

代码
public class CountryReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO Auto-generated method stub
        String str = getResultData();

        Toast.makeText(context, "乡_>>"+str, 1).show();

        setResultData("有序广播-100");

        // 终止广播
        //abortBroadcast();
    }
}
清单文件
<!-- 省长优先级 最高优先级-->
        <receiver android:name="com.elnui.day07_receiver.ProvienceReceiver">
            <intent-filter android:priority="1000">
                <action android:name="com.elnui.sendOrderBroadcast"/>
            </intent-filter>
        </receiver>

        <!-- 市长优先级 -->
        <receiver android:name="com.elnui.day07_receiver.CityReceiver">
            <intent-filter android:priority="100">
                <action android:name="com.elnui.sendOrderBroadcast"/>
            </intent-filter>
        </receiver>

        <!-- 乡长优先级 -->
        <receiver android:name="com.elnui.day07_receiver.CountryReceiver">
            <intent-filter android:priority="10">
                <action android:name="com.elnui.sendOrderBroadcast"/>
            </intent-filter>
        </receiver>

        <!-- 村民优先级 -->
        <receiver android:name="com.elnui.day07_receiver.PeopleReceiver">
            <intent-filter android:priority="1">
                <action android:name="com.elnui.sendOrderBroadcast"/>
            </intent-filter>
        </receiver>

3.最终接收者

public class FinalReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO Auto-generated method stub
        String str = getResultData();

        Toast.makeText(context, "报告_>>"+str, 1).show();
    }
}
说明:最终接收者无需再清单文件中配置

4.abortBroadcast()

终止广播

5.有序和无序广播的区别

  1. 无序广播不可以被终止,调用abortBroadcast()会在日志文件中打印警告
  2. 无序广播数据不可以修改

五、特殊广播接收者

操作特别频繁的广播事件,比如屏幕的锁屏和解锁,电池电量的变化。这种事件的广播在清单文件注册无效

5-1.注册广播接收者的两种方式

1. 使用代码动态注册 Context.registerReceiver(BroadcastReceiver receiver, IntentFilter filter)

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 动态去注册广播接收者
        ScreenReceiver sc = new ScreenReceiver();
        /*
         *      <action android:name="android.intent.action.SCREEN_OFF"/>
                <action android:name="android.intent.action.SCREEN_ON"/>
         * */
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction("android.intent.action.SCREEN_OFF");
        intentFilter.addAction("android.intent.action.SCREEN_ON");
        registerReceiver(sc, intentFilter);
    }
}

04-16 10:24:40.719: E/ActivityThread(2270): android.app.IntentReceiverLeaked:
Activity com.elnui.day07_broadcast.MainActivity has leaked IntentReceiver com.elnui.day07_broadcast.ScreenReceiver@b0fc74e8
that was originally registered here. Are you missing a call to unregisterReceiver()?

注意,当Activity销毁的时候,要取消注册广播接收者unregisterReceiver()

2. 在清单文件通过receiver节点静态注册

六、样式和主题

6-1.样式

样式的作用一般在控件上,样式的作用范围比较窄

6-2.主题

主题一般作用在Activity或者Application节点下,作用范围相抵较大

6-3.二者定义的方式一样

七、国际化

i18n
在res目录下创建不同国家语言环境的目录即可,如values-ch,values-en..

八、常见对话框

8-1.Toast

8-2.普通对话框

public void click1(View v){
        // 通过Builder构建器来构造
        AlertDialog.Builder builder = new Builder(this);

        builder.setTitle("警告"); // 标题
        builder.setMessage("世界上最遥远的距离是没有网络");   //内容
        builder.setPositiveButton("确定", new OnClickListener() {

            public void onClick(DialogInterface dialog, int which) {
                // TODO Auto-generated method stub
                System.out.println("___点击了确定按钮");
            }
        }); //
        builder.setNegativeButton("取消", new OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which) {
                // TODO Auto-generated method stub
                System.out.println("___点击了取消按钮");
            }
        }); //
        builder.show();
    }

8-3.单选对话框

    // 点击,弹出一个单选对话框
    public void click2(View v){
        // 通过Builder构建器来构造
        AlertDialog.Builder builder = new Builder(this);

        builder.setTitle("请选择课程");
        items = new String[] {"安卓","IOS","C","C++","C#"};
        builder.setSingleChoiceItems(items, 0, new OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which) {
                // TODO Auto-generated method stub
                System.out.println("___点击了单选按钮");

                // 取出选择的内容
                String str = items[which];
                Toast.makeText(getApplicationContext(), str, 1).show();
                // 关闭单选框
                dialog.dismiss();
            }
        });
        builder.show();
    }

8-4.多选对话框

    // 点击,弹出一个多选对话框
    public void click3(View v){
        // 通过Builder构建器来构造
        AlertDialog.Builder builder = new Builder(this);
        builder.setTitle("请选择水果");
        final String frults[] = new String[] {"苹果","西瓜","桔子","榴莲","哈密瓜"};
        checkedItems = new boolean[] {true,false,false,false,false};
        builder.setMultiChoiceItems(frults, checkedItems, new OnMultiChoiceClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which, boolean isChecked) {
                // TODO Auto-generated method stub

            }
        });
        builder.setPositiveButton("确定", new OnClickListener() {
            StringBuffer sb = new StringBuffer();
            @Override
            public void onClick(DialogInterface dialog, int which) {
                // TODO Auto-generated method stub
                // 把选中的条目数据取出来
                for (int i = 0; i < checkedItems.length; i++) {
                    if(checkedItems[i]){
                        String frult = frults[i];
                        sb.append(frult + "-");
                    }
                }
                Toast.makeText(getApplicationContext(), sb.toString(), 1).show();

                // 关闭单选框
                dialog.dismiss();
            }
        });
        builder.show();
    }

8-5.进度条对话框

PrograssBar

与进度相关的控件,都可以在子线程更新UI

    // 点击,弹出进度条对话框
    public void click4(View v){
        final ProgressDialog dialog = new ProgressDialog(this);
        dialog.setTitle("正在玩命加载。。。。");  

        // 设置进度条样式
        dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);

        // 线程
        new Thread(){
            @Override
            public void run() {
                // TODO Auto-generated method stub

                // 设置最大进度
                dialog.setMax(100);
                for (int i = 0; i < 100; i++) {
                    // 设置进度
                    dialog.setProgress(i);

                    // 延时
                    SystemClock.sleep(50);
                    if(dialog.getProgress() == 99){
                        dialog.dismiss();
                    }
                }
                super.run();
            }
        }.start();;

        // 最后show()
        dialog.show();
    }

九、两种上下文的区别

9-1.getApplicationContext()

返回的对象是Context对象【父类】

9-2.this

最终继承Context对象【子类】
注意: 对话框只能用this

十、安卓中的动画

10-1.帧动画

  • 加载一系列的图片资源
  • The AnimationDrawable class is the basis for Drawable animations.
    res/drawable/my_animation.xml
  • 在android2.3之前的手机上需要用兼容性写法,使用线程
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="true">
    <item android:drawable="@drawable/girl_1" android:duration="200" />
    <item android:drawable="@drawable/girl_2" android:duration="200" />
    <item android:drawable="@drawable/girl_3" android:duration="200" />
    <item android:drawable="@drawable/girl_4" android:duration="200" />
    <item android:drawable="@drawable/girl_5" android:duration="200" />
    <item android:drawable="@drawable/girl_6" android:duration="200" />
    <item android:drawable="@drawable/girl_7" android:duration="200" />
    <item android:drawable="@drawable/girl_8" android:duration="200" />
    <item android:drawable="@drawable/girl_9" android:duration="200" />
    <item android:drawable="@drawable/girl_10" android:duration="200" />
    <item android:drawable="@drawable/girl_11" android:duration="200" />
</animation-list>

onCreat()

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ImageView rocketImage  = (ImageView)findViewById(R.id.iv);

        // 设置背景资源
        rocketImage.setBackgroundResource(R.drawable.my_animation);

        // 获取AnimationDraw类型
        AnimationDrawable rocketAnimation = (AnimationDrawable) rocketImage.getBackground();

        // 开启动画
        rocketAnimation.start();
    }

10-2.View动画(补间动画)

10-3.属性动画

笔记:

笔记一:Android TextView 文字居中

两种方法

  • 在xml文件设置:Android:gravity=”center”
  • 在程序中设置:m_TxtTitle.setGravity(Gravity.CENTER);
android:gravity和android:layout_gravity的区别在于前者对控件内部操作,后者是对整个控件操作
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值