Android切近实战(九)

简介:

一个月前还是夏季,如今却已是冬季,西安真的是没有秋季和春季。OK,废话不多说,今天要说的是andriod内部的拨电话broadcast以及提一下AsyncTask。


咱们在看这篇博客之前,先看看我的那篇<<Windows Mobile 5 编程体验3>>。在那篇文章我提到了一个网站,可以获取手机号码归属地,天气预报等等一些webservice。下图是我当时在windows mobile模拟器上实现的效果,说到这个mobile,我本来是很想去学windows phone开发的,谁想还要交费买账号,太麻烦了,我放弃了,还不如学android呢,写个程序随便放上去了。不说了,看下图

wKioL1RgHZ2iPhDVAADKg_xynbo131.jpg

是不是这样呢,我当时说了,这个号码谁随便输入的,如有雷同,纯属巧合。


OK,我们接下来看看这个网站WebService网站,进去之后,我们点击国内手机号码归属地查询WEB服务

wKioL1RgHnuRgIKMAAGjKBXLSlw138.jpg

进去之后,我们查看如下方法getMobileCodeInfo

wKioL1RgHsniPaqyAADn_d7jaE4704.jpg

OK,我们看到了该WebService得request请求参数和response返回结果。

wKiom1RgHv_BYB_dAALSfO4XROA152.jpg

那OK,知道了这些,我们何愁调用呢,接下来就看我们的android客户端如何调用它。


首先我们这次的设计是当activity启动后,我们拿到本机的号码。当用户播出电话的时候,先拿到本机号码归属地,再拿到播出号码的归属地,两个号码归属地进行对比,如果归属地不一致,则加拨17951或者17911。

首先来看本机号码的获取,我们现在activity中定义一个公开的变量

public String nativePhoneNumber;

在OnCreate方法中,我们拿到本机号码

1
2
3
4
5
6
private  String GetNativePhoneNumber(){
         TelephonyManager telephonyManager = (TelephonyManager) this
         .getSystemService(Context.TELEPHONY_SERVICE);
         
         return  telephonyManager.getLine1Number();
     }

ok,拿到本机号码后,我们来看拨打这块的处理。我们知道,android有很多的内部广播,比如电池电量低,打电话,收短信,手机重启等等。这些广播我们都可以接收到,这样我们就可以实现一些功能,比如IP拨号,电池电量低自动调整屏幕亮度,切断网络等一些手机管理软件类似于360上面的一些功能。


这里我们接收拨出电话广播的代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public  class  IpDialBroadCastReceiver  extends  BroadcastReceiver {
     final  String IPChinaMobilePrefix =  "17951" ;
     final  String IPChinaUnionPrefix =  "17911" ;
     final  String ChinaMobile= "移动" ;
     final  String ChinaUnion= "联通" ;
     
     @Override
     public  void  onReceive(Context context, Intent intent) {
         String callNumber = getResultData();
         
         //ProgressDialog pg=punchinalarm.owner.progressDialog;
         //new MobileAdressTask(pg,callNumber).execute(callNumber);
         
         String nativePhoneNumber = punchinalarm.owner.nativePhoneNumber;
         
         String nativeAddress= punchinalarm.GetMobileAddress(nativePhoneNumber).toString();
         String callAddress = punchinalarm.GetMobileAddress(callNumber).toString();
         
         String newIPPhoneNumber= "" ;
         if (!nativeAddress.equalsIgnoreCase(callAddress)){
             if (nativeAddress.contains(ChinaMobile))
             {
                 newIPPhoneNumber = IPChinaMobilePrefix.concat(callNumber);
             }
             else
             {
                 newIPPhoneNumber = IPChinaUnionPrefix.concat(callNumber);
             }
             
             setResultData(newIPPhoneNumber);
         }
     }
}

在这里我们区分了联通和移动。当我们接收到打电话的广播之后,先拿到本机号码的归属地和所播电话的归属地进行对比,如果不一致,则加拨IP。这里主要是看一下punchinalarm.GetMobileAddress这个方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public  static  SoapObject GetMobileAddress(String mobileNumber) {
         SoapObject request =  new  SoapObject(NAMESPACE, METHOD_NAME);
         PropertyInfo pi =  new  PropertyInfo();
         pi.setName( "mobileCode" );
         pi.setType(String. class );
         pi.setValue(mobileNumber);
         request.addProperty(pi);
         
         pi= new  PropertyInfo();
         pi.setName( "userID" );
         pi.setType(String. class );
         pi.setValue( "" );
         request.addProperty(pi);
 
         SoapSerializationEnvelope soapEnvelope =  new  SoapSerializationEnvelope(
                 SoapEnvelope.VER11);
         soapEnvelope.dotNet =  true ;
         HttpTransportSE httpTS =  new  HttpTransportSE(URL);
         soapEnvelope.bodyOut = request;
         soapEnvelope.setOutputSoapObject(request); // 设置请求参数
 
         try  {
             httpTS.call(SOAP_ACTION, soapEnvelope);
         catch  (IOException e) {
             // TODO Auto-generated catch block
             e.printStackTrace();
         catch  (XmlPullParserException e) {
             // TODO Auto-generated catch block
             e.printStackTrace();
         }
 
         SoapObject result = (SoapObject) soapEnvelope.bodyIn;
         return  result;
     }

我们需要注意的就是NAMESPACE,METHOD_NAME,URL,SOAPACTION等。

1
2
3
4
final  static  String NAMESPACE =  "http://WebXml.com.cn/" ;
     final  static  String METHOD_NAME =  "getMobileCodeInfo" ;
     final  static  String SOAP_ACTION =  "http://WebXml.com.cn/getMobileCodeInfo" ;
     final  static  String URL =  "http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl" ;

如果大家不知道这些变量该怎么取,看下面

wKioL1RgLu2Qr3tvAALX9eau0kw533.jpg

nameSpace知道了。

wKioL1RgL0bxcAIzAAFdY62CA5A256.jpg

soapAction知道了,URL也知道了,MethodName也知道了。

好了,我们给webservice传入两个参数,userID不用传,具体的参数如何传看webservice中的描述。

拿到这两个归属地之后,我们重新设置拨号号码

setResultData(newIPPhoneNumber);

相当于对当前非IP拨号进行拦截,再进行IP拨号。我们先看看在模拟器中的效果。经过调试,我们发现本机号码是15555215554,归属地是安徽,运营商是联通(如有雷同,纯属巧合)

wKiom1RgMbKjp_g2AACvU0uzirE115.jpgwKioL1RgMnzhT5sxAAC7JmI4up4905.jpg

拨打的号码是13555556666,归属地是黑龙江,运营商是移动(如有雷同,纯属巧合)

wKioL1RgMkCzmzlAAACulHljQuI126.jpgwKiom1RgMnqytg4HAACxfMXQbEM374.jpg


所以两个归属地不一样,而且本机是联通,所以加拨17911。

wKioL1RgM5qA67hRAAJVm3shFzY797.jpg

OK,我们再看看在真机中的情况。结果报错,wifi连接着呢,为什么报错?找了半天原因,原来是我的这个APP没有开启网络权限。

wKioL1RgNbmT1qlAAAI0XHLtwo8112.jpg

就是这个个人理财APP,我们看一下效果

wKiom1RgNdXQUARzAAHV-DF2tLs174.jpg

看见了吧,自动加拨了17951。最后我们再看一下异步的实现

wKiom1RgPOjwWvrmAAIL8DCjB3k462.jpg

代码如下,在获取通话广播之后,我们开启一个异步task去检测归属地

1
2
ProgressDialog pg=punchinalarm.owner.progressDialog;
         new  MobileAdressTask(pg,callNumber).execute(callNumber);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public  class  MobileAdressTask  extends  AsyncTask<String, Integer, String> {
     final  String IPPrefix =  "17951" ;
     String callNumber;
     ProgressDialog progressDialog;
 
     public  MobileAdressTask(ProgressDialog progressDialog, String callNumber) {
         this .progressDialog = progressDialog;
         this .callNumber = callNumber;
     }
 
     protected  void  onPreExecute() {
         super .onPreExecute();
         progressDialog.show();
     }
 
     protected  String doInBackground(String... params) {
         publishProgress( 5 );
         String s = params[ 0 ];
         SoapObject soapObjValue = punchinalarm.GetMobileAddress(params[ 0 ]);
         publishProgress( 100 );
         return  soapObjValue ==  null  ""  : soapObjValue.toString();
     }
 
     protected  void  onProgressUpdate(Integer... values) {
         super .onProgressUpdate(values);
         progressDialog.setProgress(values[ 0 ]);
     }
 
     protected  void  onPostExecute(String result) {
         super .onPostExecute(result);
 
         if  (!result.contains( "西安" ) && !callNumber.startsWith(IPPrefix)) {
             String newnumber = IPPrefix.concat(callNumber);
             Intent dialIntent =  new  Intent(Intent.ACTION_CALL, Uri.parse( "tel:"
                     + newnumber));
             punchinalarm.owner.startActivity(dialIntent);
         }
         progressDialog.dismiss();
     }
}

在doInBackGroud中我们得到归属地并模拟进度条。得到归属地之后,我们判断如果不是西安的号码并且没有加拨17951我们就加拨17951。此时会有一个号码是hold状态。

wKiom1RgQKXSk2PEAAI_odynZj4914.jpg

OK,最后看一下真机效果

wKiom1RgYdbSD37eAAJ6xh4VrcY413.jpg

最后,别忘了这三个配置,前两个是读取手机信息和处理拨电话权限,最后一个是静态注册广播接收者。这个接受者就是上面提到的IpDialBroadCastReceiver,这个广播接收者只接收android.intent.action.NEW_OUTGOING_CALL这个action发出的广播。其中要注意的是这个receiver是注册在Application节点中的。

1
2
3
4
5
6
7
< uses-permission  android:name = "android.permission.READ_PHONE_STATE"  />
< uses-permission  android:name = "android.permission.PROCESS_OUTGOING_CALLS" />
< receiver  android:name = "bruce.broadcastor.IpDialBroadCastReceiver" >
             < intent-filter  android:priority = "1" >
            < action  android:name = "android.intent.action.NEW_OUTGOING_CALL" />
             </ intent-filter >
         </ receiver >

哥们博客货真价实,小米3测试机,需要源码的同学去下载源码下载



本文转自 BruceAndLee 51CTO博客,原文链接:http://blog.51cto.com/leelei/1574894,如需转载请自行联系原作者

相关文章
|
3月前
Android4.1.0实战教程---自动阅读小说
Android4.1.0实战教程---自动阅读小说
35 0
|
4月前
|
Android开发
【Android App】蓝牙的设备配对、音频传输、点对点通信的讲解及实战(附源码和演示 超详细)
【Android App】蓝牙的设备配对、音频传输、点对点通信的讲解及实战(附源码和演示 超详细)
92 0
|
4月前
|
JSON Java 定位技术
【Android App】GPS获取定位经纬度和根据经纬度获取详细地址讲解及实战(附源码和演示 超详细)
【Android App】GPS获取定位经纬度和根据经纬度获取详细地址讲解及实战(附源码和演示 超详细)
235 0
|
30天前
|
缓存 移动开发 Java
构建高效Android应用:内存优化实战指南
在移动开发领域,性能优化是提升用户体验的关键因素之一。特别是对于Android应用而言,由于设备和版本的多样性,内存管理成为开发者面临的一大挑战。本文将深入探讨Android内存优化的策略和技术,包括内存泄漏的诊断与解决、合理的数据结构选择、以及有效的资源释放机制。通过实际案例分析,我们旨在为开发者提供一套实用的内存优化工具和方法,以构建更加流畅和高效的Android应用。
|
2月前
|
算法 Java Android开发
安卓逆向 -- 实战某峰窝APP(静态分析)
安卓逆向 -- 实战某峰窝APP(静态分析)
26 0
|
2月前
|
网络协议 算法 Android开发
安卓逆向 -- 实战某峰窝APP(动态分析)
安卓逆向 -- 实战某峰窝APP(动态分析)
31 4
|
4月前
|
Android开发 Kotlin
Android实战演练(kotlin版),词汇记录APP
Android实战演练(kotlin版),词汇记录APP
38 0
|
4月前
|
Web App开发 JSON Android开发
【Android App】实战项目之仿微信的视频通话(附源码和演示 超详细必看)
【Android App】实战项目之仿微信的视频通话(附源码和演示 超详细必看)
82 0
|
4月前
|
Web App开发 Android开发 ice
【Android App】给App集成WebRTC实现视频发送和接受实战(附源码和演示 超详细)
【Android App】给App集成WebRTC实现视频发送和接受实战(附源码和演示 超详细)
93 1
|
4月前
|
算法 Android开发
【Android App】二维码的讲解及生成属于自己的二维码实战(附源码和演示 超详细必看)
【Android App】二维码的讲解及生成属于自己的二维码实战(附源码和演示 超详细必看)
81 0