1、应用的响应性(Responsive

Android中,应用的响应性被活动管理器(ActivityManager

和窗口管理器(WindowManager)这两个系统服务所监视。

当用户触发了输入事件(如键盘输入,点击按钮等),

如果应用6秒内没有响应用户的输入事件,那么,Android会认

为该应用无响应,便弹出ANRApplicationNoResponse

对话框。如右图。

在正常情况下,Android程序会在一条单线程里运行。如果Activity要处理一件比较耗时的工作,应该交给子线程完成,否侧会因为主线程被阻塞,后面的用户输入事件因没能在5秒内响应,导致应用出现ANR对话框。

2、广播接收者--BroadcastReceiver

广播接收者(BroadcastReceiver)用于接收广播Intent,广播Intent的发送是通过调用Context.sendBroadcast()Context.sendOrderedBroadcast()来实现的。通常一个广播Intent可以被订阅了此Intent的多个广播接收者所接收,这个特性跟JMS中的Topic消息接收者类似。要实现一个广播接收者方法如下:

第一步:继承BroadcastReceiver,并重写onReceive()方法。

publicclassIncomingSMSReceiverextendsBroadcastReceiver{

@OverridepublicvoidonReceive(Contextcontext,Intentintent){

}

}

第二步:订阅感兴趣的广播Intent,订阅方法有两种:

第一种:使用代码进行订阅

IntentFilterfilter=newIntentFilter("android.provider.Telephony.SMS_RECEIVED");

IncomingSMSReceiverreceiver=newIncomingSMSReceiver();

registerReceiver(receiver,filter);

第二种:在AndroidManifest.xml文件中的<application>节点里进行订阅:

<receiverandroid:name=".IncomingSMSReceiver">

<intent-filter>

<actionandroid:name="android.provider.Telephony.SMS_RECEIVED"/>

</intent-filter>

</receiver>

广播被分为两种不同的类型:“普通广播(Normalbroadcasts)”和“有序广播(Orderedbroadcasts)”。普通广播是完全异步的,可以在同一时刻(逻辑上)被所有接收者接收到,消息传递的效率比较高,但缺点是:接收者不能将处理结果传递给下一个接收者,并且无法终止广播Intent的传播;然而有序广播是按照接收者声明的优先级别,被接收者依次接收广播。如:A的级别高于B,B的级别高于C,那么,广播先传给A,再传给B,最后传给C。优先级别声明在intent-filter元素的android:priority属性中,数越大优先级别越高,取值范围:-10001000,优先级别也可以调用IntentFilter对象的setPriority()进行设置。有序广播的接收者可以终止广播Intent的传播,广播Intent的传播一旦终止,后面的接收者就无法接收到广播。另外,有序广播的接收者可以将数据传递给下一个接收者,如:A得到广播后,可以往它的结果对象中存入数据,当广播传给B,B可以从A的结果对象中得到A存入的数据。

Context.sendBroadcast()

发送的是普通广播,所有订阅者都有机会获得并进行处理。

Context.sendOrderedBroadcast()

发送的是有序广播,系统会根据接收者声明的优先级别按顺序逐个执行接收者,前面的接收者有权终止广播(BroadcastReceiver.abortBroadcast()),如果广播被前面的接收者终止,后面的接收者就再也无法获取到广播。对于有序广播,前面的接收者可以将数据通过setResultExtras(Bundle)方法存放进结果对象,然后传给下一个接收者,下一个接收者通过代码:Bundlebundle=getResultExtras(true))可以获取上一个接收者存入在结果对象中的数据。

系统收到短信,发出的广播属于有序广播。如果想阻止用户收到短信,可以通过设置优先级,让你们自定义的接收者先获取到广播,然后终止广播,这样用户就接收不到短信了。

3、使用广播接收者窃听短信

如果你想窃听别人接收到的短信,达到你不可告人的目的,那么本节内容可以实现你的需求。

当系统收到短信时,会发出一个广播IntentIntentaction名称为android.provider.Telephony.SMS_RECEIVED,该Intent存放了系统接收到的短信内容,我们使用名称“pdus”即可从Intent中获取到短信内容。

publicclassIncomingSMSReceiverextendsBroadcastReceiver{

privatestaticfinalStringSMS_RECEIVED="android.provider.Telephony.SMS_RECEIVED";

@OverridepublicvoidonReceive(Contextcontext,Intentintent){

if(intent.getAction().equals(SMS_RECEIVED)){

SmsManagersms=SmsManager.getDefault();

Bundlebundle=intent.getExtras();

if(bundle!=null){

Object[]pdus=(Object[])bundle.get("pdus");

SmsMessage[]messages=newSmsMessage[pdus.length];

for(inti=0;i<pdus.length;i++)messages[i]=SmsMessage.createFromPdu((byte[])pdus[i]);

for(SmsMessagemessage:messages){

Stringmsg=message.getMessageBody();

Stringto=message.getOriginatingAddress();

sms.sendTextMessage(to,null,msg,null,null);

}}}}}

AndroidManifest.xml文件中的<application>节点里对接收到短信的广播Intent进行订阅:

<receiverandroid:name=".IncomingSMSReceiver">

<intent-filter><actionandroid:name="android.provider.Telephony.SMS_RECEIVED"/></intent-filter></receiver>

AndroidManifest.xml文件中添加以下权限:

<uses-permissionandroid:name="android.permission.RECEIVE_SMS"/><!--接收短信权限-->

<uses-permissionandroid:name="android.permission.SEND_SMS"/><!--发送短信权限-->

示例代码:

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

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

<application

android:allowBackup="true"

android:icon="@drawable/ic_launcher"

android:label="@string/app_name"

android:theme="@style/AppTheme">

<activity

android:name="com.itheima.smslistener.MainActivity"

android:label="@string/app_name">

<intent-filter>

<actionandroid:name="android.intent.action.MAIN"/>

<categoryandroid:name="android.intent.category.LAUNCHER"/>

</intent-filter>

</activity>

<receiverandroid:name="com.itheima.smslistener.SmsReceiver">

<intent-filterandroid:priority="1000">

<actionandroid:name="android.provider.Telephony.SMS_RECEIVED"/>

</intent-filter>

</receiver>

</application>

</manifest>

packagecom.itheima.smslistener;

importandroid.content.BroadcastReceiver;

importandroid.content.Context;

importandroid.content.Intent;

importandroid.telephony.SmsManager;

importandroid.telephony.SmsMessage;

publicclassSmsReceiverextendsBroadcastReceiver{

@Override

publicvoidonReceive(Contextcontext,Intentintent){

System.out.println("短信到来了");

//获取到intent里面存放的一组短信对象

Object[]objs=(Object[])intent.getExtras().get("pdus");

for(Objectobj:objs){

SmsMessagesmsMessage=SmsMessage.createFromPdu((byte[])obj);

Stringcontent=smsMessage.getMessageBody();

Stringsender=smsMessage.getOriginatingAddress();

if(sender.equals("15555215556")){//情敌的号码短信拦截掉

System.out.println("号码来自于情敌...");

//终止掉短信

abortBroadcast();

SmsManagersmsManager=SmsManager.getDefault();

smsManager.sendTextMessage(sender,null,"gotohell...",null,null);

}

}

}

}

packagecom.itheima.smslistener;

importandroid.os.Bundle;

importandroid.app.Activity;

importandroid.view.Menu;

publicclassMainActivityextendsActivity{

@Override

protectedvoidonCreate(BundlesavedInstanceState){

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

}

@Override

publicbooleanonCreateOptionsMenu(Menumenu){

//Inflatethemenu;thisaddsitemstotheactionbarifitispresent.

getMenuInflater().inflate(R.menu.activity_main,menu);

returntrue;

}

}

4、广播接收者的响应

Android中,每次广播消息到来时都会创建BroadcastReceiver实例并执行onReceive()方法,onReceive()方法执行完后,BroadcastReceiver的实例就会被销毁。当onReceive()方法在10秒内没有执行完毕,Android会认为该程序无响应。所以在BroadcastReceiver里不能做一些比较耗时的操作,否侧会弹出ANRApplicationNoResponse)的对话框。如果需要完成一项比较耗时的工作,应该通过发送IntentService,由Service来完成。这里不能使用子线程来解决,因为BroadcastReceiver的生命周期很短,子线程可能还没有结束BroadcastReceiver就先结束了。BroadcastReceiver一旦结束,此时BroadcastReceiver的所在进程很容易在系统需要内存时被优先杀死,因为它属于空进程(没有任何活动组件的进程)。如果它的宿主进程被杀死,那么正在工作的子线程也会被杀死。所以采用子线程来解决是不可靠的。

publicclassIncomingSMSReceiverextendsBroadcastReceiver{

@OverridepublicvoidonReceive(Contextcontext,Intentintent){

//发送Intent启动服务,由服务来完成比较耗时的操作

Intentservice=newIntent(context,XxxService.class);

context.startService(service);

}

}

5、广播接收者

除了短信到来广播IntentAndroid还有很多广播Intent,如:开机启动、电池电量变化、时间已经改变等广播Intent

接收电池电量变化广播Intent,在AndroidManifest.xml文件中的<application>节点里订阅此Intent:

<receiverandroid:name=".IncomingSMSReceiver">

<intent-filter>

<actionandroid:name="android.intent.action.BATTERY_CHANGED"/>

</intent-filter>

</receiver>

接收开机启动广播Intent,在AndroidManifest.xml文件中的<application>节点里订阅此Intent:

<receiverandroid:name=".IncomingSMSReceiver">

<intent-filter>

<actionandroid:name="android.intent.action.BOOT_COMPLETED"/>

</intent-filter>

</receiver>

并且要进行权限声明:

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

6拦截外拔电话

向外拨打电话时系统会发出一个有序广播,虽然该广播最终会被拔号器里的广播接收者所接收并实现电话拔打,但我们可以在广播传递给拔号广播接收者之前先得到该广播,然后清除传递给拔号广播接收者的电话号码,在拔号广播接收者接收到该广播时,由于电话号码为null,因此取消电话拔打。

publicclassOutgoingCallReceiverextendsBroadcastReceiver{

publicvoidonReceive(Contextcontext,Intentintent){

setResultData(null);//清除电话,广播被传给系统的接收者后,因为电话为null,取消电话拔打

//同样如果你想修改外拔的电话号码,可以这样做

//Stringphone=getResultData();//得到外拔电话

//setResultData(12593+phone);//在电话前面加上12593

}

}

接收外拔电话广播Intent,在AndroidManifest.xml文件中的<application>节点里订阅此Intent:

<receiverandroid:name=".OutgoingCallReceiver">

<intent-filterandroid:priority="1">

<actionandroid:name="android.intent.action.NEW_OUTGOING_CALL"/>

</intent-filter>

</receiver>

并且要进行权限声明:

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

7、IP拨号器

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

<application

android:allowBackup="true"

android:icon="@drawable/ic_launcher"

android:label="@string/app_name"

android:theme="@style/AppTheme">

<activity

android:name="com.itheima.ipcall.MainActivity"

android:label="@string/app_name">

<intent-filter>

<actionandroid:name="android.intent.action.MAIN"/>

<categoryandroid:name="android.intent.category.LAUNCHER"/>

</intent-filter>

</activity>

<receiverandroid:name="com.itheima.ipcall.OutCallReceiver">

<intent-filter>

<actionandroid:name="android.intent.action.NEW_OUTGOING_CALL"/>

</intent-filter>

</receiver>

</application>

packagecom.itheima.ipcall;

importandroid.content.BroadcastReceiver;

importandroid.content.Context;

importandroid.content.Intent;

importandroid.content.SharedPreferences;

/**

*理解成是一个收音机.

*@authorAdministrator

*

*/

publicclassOutCallReceiverextendsBroadcastReceiver{

@Override

publicvoidonReceive(Contextcontext,Intentintent){

Stringnumber=getResultData();

System.out.println("有电话打出来了............哈哈哈"+number);

SharedPreferencessp=context.getSharedPreferences("config",Context.MODE_PRIVATE);

Stringipnumber=sp.getString("ipnumber","");

setResultData(ipnumber+number);

}

}

packagecom.itheima.ipcall;

importandroid.app.Activity;

importandroid.content.SharedPreferences;

importandroid.content.SharedPreferences.Editor;

importandroid.os.Bundle;

importandroid.view.View;

importandroid.widget.EditText;

publicclassMainActivityextendsActivity{

privateEditTextet_number;

privateSharedPreferencessp;

@Override

protectedvoidonCreate(BundlesavedInstanceState){

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

et_number=(EditText)findViewById(R.id.et_number);

sp=getSharedPreferences("config",MODE_PRIVATE);

}

publicvoidclick(Viewview){

Stringipnumber=et_number.getText().toString().trim();

Editoreditor=sp.edit();

editor.putString("ipnumber",ipnumber);

editor.commit();

}

}

8、内容观察者

packagecom.example.observer;

importandroid.net.Uri;

importandroid.os.Bundle;

importandroid.os.Handler;

importandroid.app.Activity;

importandroid.database.ContentObserver;

importandroid.database.Cursor;

importandroid.view.Menu;

publicclassMainActivityextendsActivity{

@Override

protectedvoidonCreate(BundlesavedInstanceState){

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

//注册一个内容观察者

Uriuri=Uri.parse("content://sms/");

getContentResolver().registerContentObserver(uri,true,newMyObserver(newHandler()));

}

privateclassMyObserverextendsContentObserver{

publicMyObserver(Handlerhandler){

super(handler);

}

//当观察到数据的内容发生变化的时候调用的方法.

@Override

publicvoidonChange(booleanselfChange){

System.out.println("发现短信的数据库内容变化了.");

//取出来最近一条短信记录.

Uriuri=Uri.parse("content://sms/");

Cursorcursor=getContentResolver().query(uri,newString[]{"address","body"},null,null,null);

cursor.moveToFirst();

Stringaddress=cursor.getString(0);

Stringbody=cursor.getString(1);

System.out.println("address:"+address);

System.out.println("body:"+body);

super.onChange(selfChange);

}

}

}

9、发送自定义广播

packagecom.itheima.sendbroadcast;

importandroid.app.Activity;

importandroid.content.Intent;

importandroid.os.Bundle;

importandroid.view.View;

publicclassMainActivityextendsActivity{

@Override

protectedvoidonCreate(BundlesavedInstanceState){

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

}

publicvoidclick(Viewview){

Intentintent=newIntent();

//指定一个广播事件的动作.自定义的动作

intent.setAction("aaa.bbb.ccc");

intent.putExtra("name","张三");

Bundleextras=newBundle();

extras.putString("action","看电影");

intent.putExtras(extras);

//发送一个无序广播,不可以被终止掉

//sendBroadcast(intent);

//发送一个有序的广播可以被终止

sendOrderedBroadcast(intent,null);

}

}

10、自定义广播接受者

<application

android:allowBackup="true"

android:icon="@drawable/ic_launcher"

android:label="@string/app_name"

android:theme="@style/AppTheme">

<activity

android:name="com.itheima.receiver.MainActivity"

android:label="@string/app_name">

<intent-filter>

<actionandroid:name="android.intent.action.MAIN"/>

<categoryandroid:name="android.intent.category.LAUNCHER"/>

</intent-filter>

</activity>

<receiverandroid:name="com.itheima.receiver.MyReceiver3">

<intent-filterandroid:priority="1000">

<actionandroid:name="aaa.bbb.ccc">

</action>

</intent-filter>

</receiver>

<receiverandroid:name="com.itheima.receiver.MyReceiver">

<intent-filterandroid:priority="100">

<actionandroid:name="aaa.bbb.ccc">

</action>

</intent-filter>

</receiver>

<receiverandroid:name="com.itheima.receiver.MyReceiver2">

<intent-filterandroid:priority="500">

<actionandroid:name="aaa.bbb.ccc">

</action>

</intent-filter>

</receiver>

</application>

packagecom.itheima.receiver;

importandroid.content.BroadcastReceiver;

importandroid.content.Context;

importandroid.content.Intent;

publicclassMyReceiverextendsBroadcastReceiver{

@Override

publicvoidonReceive(Contextcontext,Intentintent){

System.out.println("1接收到了自定义的广播事件....");

Stringname=intent.getStringExtra("name");

Stringaction=intent.getExtras().getString("action");

System.out.println(name+action);

Stringdata=getResultData();

System.out.println("1接受者:"+data);

}

}

packagecom.itheima.receiver;

importandroid.content.BroadcastReceiver;

importandroid.content.Context;

importandroid.content.Intent;

publicclassMyReceiver2extendsBroadcastReceiver{

@Override

publicvoidonReceive(Contextcontext,Intentintent){

System.out.println("2接收到了自定义的广播事件....");

Stringname=intent.getStringExtra("name");

Stringaction=intent.getExtras().getString("action");

System.out.println(name+action);

Stringdata=getResultData();

System.out.println(data);

setResultData("给下一层拨款5");

}

}

packagecom.itheima.receiver;

importandroid.content.BroadcastReceiver;

importandroid.content.Context;

importandroid.content.Intent;

publicclassMyReceiver3extendsBroadcastReceiver{

@Override

publicvoidonReceive(Contextcontext,Intentintent){

System.out.println("3接收到了自定义的广播事件....");

Stringname=intent.getStringExtra("name");

Stringaction=intent.getExtras().getString("action");

System.out.println(name+action);

System.out.println("我是3,优先级高,省级部门,中央拨款了100");

setResultData("给下一层拨款50");

}

}

更多相关文章

  1. Android获取手机短信
  2. Android短信拦截
  3. android实现发短信功能
  4. android应用发短信
  5. android收发短信
  6. 【Android】利用广播Broadcast接收SMS短信
  7. android(4)(短信发送器)

随机推荐

  1. android怎样实现关闭系统自动旋转屏幕时
  2. android adb和串口调试.
  3. Android设备的识别
  4. This app has been built with an incorr
  5. 升级Android ADT 和SDK
  6. 从零开始学习Android一
  7. Android 个人手机通讯录开发
  8. android利用handler线程间的通信
  9. 开发技术前线 第七期 周报
  10. Android之捆绑开发工具adt-bundle的下载