10.【小萌伴Android】短信找手机功能及其实现
短信找手机有两种方式,短信找手机(声音/灯光)与短信找手机(手机定位),分别对应两种不同的情景:一种是在某个地方手机乱放找不到,另一种是手机丢失(比如掉了、被偷之类的)...
注意:该功能需要另一台手机的辅助,才能找到手机(后面即将介绍的语音找手机则不需要另一台手机辅助)
1 短信找手机(声音/灯光)
短信找手机(声音/灯光)是确定手机在某个区域后的,定位手机的准确位置,比如在家里手机乱丢找不到,在办公室忘记放在哪个同事座位上等...
1.1 原理
该功能在app中预设短信找手机密码,另一台手机发送短信,丢失的手机通过监听短信广播,如果短信内容是预设的密码,则app会播放相应的提示音乐或者打开手电筒功能(手机摄像头闪光灯),方便用户快速、准确的找到手机。
1.2 短信监听
监听短信内容,根据不同短信密码进入服务,传入不同的参数进行处理
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 |
public <span class="hljs-keyword">void</span> onReceive(Context context, Intent intent) { <span class="hljs-built_in">Object</span>[] pdus = (<span class="hljs-built_in">Object</span>[]) intent.getExtras().get(<span class="hljs-string">"pdus"</span>); <span class="hljs-keyword">for</span> (<span class="hljs-built_in">Object</span> pdu : pdus) { SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) pdu); <span class="hljs-built_in">String</span> content = smsMessage.getMessageBody(); <span class="hljs-comment">// 获取短信内容</span> <span class="hljs-built_in">String</span> msgPwd = <span class="hljs-string">""</span>; <span class="hljs-comment">// 这里读取app设置的短信找手机(声音/灯光)密码</span> <span class="hljs-built_in">String</span> msgLatlngPwd = <span class="hljs-string">""</span>; <span class="hljs-comment">// 这里读取app设置的短信找手机(手机定位)密码</span> <span class="hljs-keyword">if</span> (content == <span class="hljs-literal">null</span> || content.length() < <span class="hljs-number">6</span>) { <span class="hljs-comment">// 由于密码设置必须多于6位,短信内容小于6位不进行后续判断</span> <span class="hljs-keyword">continue</span>; } <span class="hljs-keyword">if</span> (content.trim().equals(msgPwd)) { <span class="hljs-comment">// 短信找手机(声音/灯光),具体内容到服务中进行处理</span> startService(context, E7Service.FROM_SMS_RECEIVER, smsMessage.getOriginatingAddress()); abortBroadcast(); <span class="hljs-keyword">return</span>; } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (content.trim().equals(msgLatlngPwd)) { <span class="hljs-comment">// 短信找手机(手机定位),具体内容到服务中进行处理</span> startService(context, E7Service.FROM_SMS_RECEIVER_LATLNG, smsMessage.getOriginatingAddress()); abortBroadcast(); <span class="hljs-comment">// 表示该广播已经处理完毕,该短信不会显示到系统短信列表中(部分手机该操作无效)</span> <span class="hljs-keyword">return</span>; } } } private <span class="hljs-keyword">void</span> startService(Context context, int <span class="hljs-keyword">from</span>, <span class="hljs-built_in">String</span> phoneNum) { Intent intentE7Service = <span class="hljs-keyword">new</span> Intent(context, E7Service.class); <span class="hljs-comment">// 类别,是短信找手机(声音/灯光)、短信找手机(手机定位)或者其他</span> intentE7Service.putExtra(E7Service.FROM, <span class="hljs-keyword">from</span>); <span class="hljs-comment">// 经纬度找手机,需要回复信息,所以将发送方的手机号传到服务中</span> intentE7Service.putExtra(<span class="hljs-string">"phoneNum"</span>, phoneNum);<span class="hljs-comment">//getDisplayOriginatingAddress());</span> ServiceUtil.startService(context, intentE7Service); } |
短信监听需要广播静态注册,并设置优先级,增加相应权限
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<span class="hljs-comment"><!-- start: 找手机权限 --></span> <span class="hljs-tag"><<span class="hljs-name">uses-permission</span> <span class="hljs-attr">android:name</span>=<span class="hljs-string">"android.permission.SEND_SMS"</span> /></span> <span class="hljs-tag"><<span class="hljs-name">uses-permission</span> <span class="hljs-attr">android:name</span>=<span class="hljs-string">"android.permission.READ_SMS"</span> /></span> <span class="hljs-comment"><!--<uses-permission android:name="android.permission.SEND_RESPOND_VIA_MESSAGE" /> <uses-permission android:name="android.permission.BROADCAST_SMS" />--></span> <span class="hljs-tag"><<span class="hljs-name">uses-permission</span> <span class="hljs-attr">android:name</span>=<span class="hljs-string">"android.permission.SMS_DELIVER_ACTION"</span> /></span> <span class="hljs-tag"><<span class="hljs-name">uses-permission</span> <span class="hljs-attr">android:name</span>=<span class="hljs-string">"android.permission.RECEIVE_SMS"</span>/></span> <span class="hljs-tag"><<span class="hljs-name">uses-permission</span> <span class="hljs-attr">android:name</span>=<span class="hljs-string">"android.permission.ACCESS_COARSE_LOCATION"</span> /></span> <span class="hljs-tag"><<span class="hljs-name">uses-permission</span> <span class="hljs-attr">android:name</span>=<span class="hljs-string">"android.permission.ACCESS_FINE_LOCATION"</span> /></span> <span class="hljs-tag"><<span class="hljs-name">uses-permission</span> <span class="hljs-attr">android:name</span>=<span class="hljs-string">"android.permission.REQUEST_INSTALL_PACKAGES"</span> /></span> <span class="hljs-comment"><!-- end: 找手机权限 --></span> |
1 2 3 4 5 6 7 |
<span class="hljs-tag"><<span class="hljs-name">receiver</span> <span class="hljs-attr">android:name</span>=<span class="hljs-string">".receiver.SmsReceiver"</span> <span class="hljs-attr">android:process</span>=<span class="hljs-string">":remote"</span>></span> <span class="hljs-tag"><<span class="hljs-name">intent-filter</span> <span class="hljs-attr">android:priority</span>=<span class="hljs-string">"1000"</span>></span> <span class="hljs-tag"><<span class="hljs-name">action</span> <span class="hljs-attr">android:name</span>=<span class="hljs-string">"android.provider.Telephony.SMS_RECEIVED"</span>/></span> <span class="hljs-tag"></<span class="hljs-name">intent-filter</span>></span> <span class="hljs-tag"></<span class="hljs-name">receiver</span>></span> |
1.3 服务
正常启动一个粘性(START_STICKY)服务,如果根据FROM进行不同的操作,播放声音,打开手电筒或进行定位回复短信...
另外,这里其实还有一个操作,进程保活,因为service在后台可能被杀掉,如何降低被杀掉的风险,如果被杀掉如何重新拉起...之前写过一篇,可以参考:Android进程保活(黑白手段让APP活下去)(写的时间久了点,可能有点过时,欢迎补充...)
因为保活太难,我尝试了多种方式,发了多个版本,最终始终有人反馈某些手机后台服务被杀掉了(即该功能无法使用),于是在Android 0以上版本,改为开启前台服务:
1 2 |
<span class="hljs-selector-tag">ServiceUtil</span><span class="hljs-selector-class">.startForeground</span>(<span class="hljs-selector-tag">this</span>, <span class="hljs-selector-tag">ServiceUtil</span><span class="hljs-selector-class">.E7ServiceNotifyId</span>, <span class="hljs-selector-tag">this</span><span class="hljs-selector-class">.getApplicationContext</span>(), 0, 0, 0, 0 ); |
1 2 3 4 5 6 |
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">startForeground</span><span class="hljs-params">(Service service, <span class="hljs-keyword">int</span> id, Context context, <span class="hljs-keyword">int</span> textResId, <span class="hljs-keyword">int</span> titleResId, <span class="hljs-keyword">int</span> smallIconResId, <span class="hljs-keyword">int</span> largeIconResId)</span> </span>{ <span class="hljs-keyword">if</span> (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { service.startForeground(id, getNotification(context, textResId, titleResId, smallIconResId, largeIconResId)); <span class="hljs-comment">//这个id不要和应用内的其他通知id一样,不行就写 int.maxValue() //context.startForeground(SERVICE_ID, builder.getNotification());</span> } } |
1.4 声音(预设音频播放)
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 |
<span class="hljs-comment">/** * 初始化音效 */</span> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">initMusic</span><span class="hljs-params">()</span> </span>{ soundp = <span class="hljs-keyword">new</span> SoundPool(<span class="hljs-number">50</span>, AudioManager.STREAM_MUSIC, <span class="hljs-number">100</span>); soundm = <span class="hljs-keyword">new</span> HashMap<String, Integer>(); soundm.put(SOUND_PHONE_IS_HERE, soundp.load(<span class="hljs-keyword">this</span>, R.raw.findphone, <span class="hljs-number">1</span>)); } <span class="hljs-comment">/** * 播放音效 */</span> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">playMusic</span><span class="hljs-params">(String str)</span> </span>{ <span class="hljs-comment">// // MobclickAgent.onEvent(E7App.mApp, Constant.Umeng.Send_play_music);</span> <span class="hljs-keyword">if</span> (soundp == null || soundm == null) { initMusic(); } AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE); <span class="hljs-keyword">int</span> ringMode = am.getRingerMode(); <span class="hljs-keyword">if</span> (ringMode == AudioManager.RINGER_MODE_VIBRATE || ringMode == AudioManager.RINGER_MODE_SILENT) am.setRingerMode(AudioManager.RINGER_MODE_NORMAL); <span class="hljs-keyword">int</span> now = am.getStreamVolume(AudioManager.STREAM_MUSIC);<span class="hljs-comment">//得到听筒模式的当前值</span> <span class="hljs-keyword">int</span> max = <span class="hljs-comment">/**now;//*/</span>am.getStreamMaxVolume(AudioManager.STREAM_MUSIC); am.setStreamVolume(AudioManager.STREAM_MUSIC, max, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE); soundp.play(soundm.get(str), <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">1f</span>); <span class="hljs-keyword">try</span> { <span class="hljs-comment">// 5s后将声音设置还原(播放完毕)</span> Thread.sleep(<span class="hljs-number">5000</span>); } <span class="hljs-keyword">catch</span> (Exception e) { e.printStackTrace(); } am.setStreamVolume(AudioManager.STREAM_MUSIC, now, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE); <span class="hljs-comment">// init(this);</span> } |
1.5 手电筒(灯光提醒)
参考之前文章:8.【小萌伴Android】手电筒功能及其实现
2 短信找手机(手机定位)
短信找手机(手机定位)用于完全不能确定手机的位置,定位手机的大概位置,(如手机掉在外面,手机被偷等...)该功能可以配合上面的功能使用,从而准确找到手机。
2.1 原理
该功能在app中预设短信找手机密码,另一台手机发送短信,丢失的手机通过监听短信广播,如果短信内容是预设的密码,则app会调用手机定位功能确定一个经纬度(位置),并将该经纬度通过短信回复到短信发送方。比如:A找不到手机,通过B手机发送密码(123456)到A手机,A手机接收到后,会自动进行定位,并把位置以短信的方式返回给B,B可以直接点击短信中的url打开百度地图看到A手机位置,或者从短信中拷贝经纬度,到电脑进行查询位置。
2.2 短信监听
与上面的短信监听一致,仅密码不同
2.3 后台服务
与上面的后台服务一致
2.4 位置(百度定位)
百度定位不做太多介绍,根据百度官方文档进行开发即可...这里主要是监听定位回调,得到结果后发送短信
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyLocationListener</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">BDLocationListener</span> </span>{ <span class="hljs-meta">@Override</span> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onReceiveLocation</span><span class="hljs-params">(BDLocation location)</span> </span>{ <span class="hljs-keyword">if</span> (location != <span class="hljs-keyword">null</span>) { <span class="hljs-keyword">int</span> locType = location.getLocType(); <span class="hljs-keyword">switch</span> (locType) { <span class="hljs-keyword">case</span> BDLocation.TypeNetWorkLocation: <span class="hljs-keyword">case</span> BDLocation.TypeGpsLocation: <span class="hljs-keyword">case</span> BDLocation.TypeOffLineLocation: Loc.getInstance(mLoc).stopLocation(); sendMsg(location.getLatitude(), location.getLongitude()); <span class="hljs-keyword">break</span>; } } } } |
2.5 短信回复(包含百度url)
短信发送并监听发送结果
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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
<span class="hljs-keyword">private</span> String phoneNum; <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">sendMsg</span><span class="hljs-params">(<span class="hljs-keyword">double</span> lat, <span class="hljs-keyword">double</span> lng)</span> </span>{ <span class="hljs-comment">// 拼接百度地图经纬度解析url,方便对方收到短信回复后直接点击进入地图查看位置</span> String message = <span class="hljs-string">"http://api.map.baidu.com/geocoder?"</span> + <span class="hljs-string">"location="</span> + lat + <span class="hljs-string">","</span> + lng + <span class="hljs-comment">/*"&coord_type=bd0911" +*/</span> <span class="hljs-comment">//gcj02"</span> <span class="hljs-string">"&output=html"</span> + <span class="hljs-string">"&src=e7yoo【"</span> + OsUtil.getAppName(<span class="hljs-keyword">this</span>) + <span class="hljs-string">"】"</span>; <span class="hljs-keyword">synchronized</span> (phoneNumObj) { <span class="hljs-keyword">if</span>(phoneNum == <span class="hljs-keyword">null</span>) { <span class="hljs-comment">// CrashReport.postCatchedException(new Exception("phoneNum == null"));</span> <span class="hljs-keyword">return</span>; } String phoneNum = <span class="hljs-keyword">this</span>.phoneNum; sendMsg(phoneNum, message); <span class="hljs-keyword">this</span>.phoneNum = <span class="hljs-keyword">null</span>; } <span class="hljs-comment">// MobclickAgent.onEvent(E7App.mApp, Constant.Umeng.Send_sms_latlng);</span> } <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">sendMsg</span><span class="hljs-params">(String phoneNum, String message)</span> </span>{ <span class="hljs-keyword">if</span>(phoneNum == <span class="hljs-keyword">null</span>) { <span class="hljs-comment">// // MobclickAgent.onEvent(E7App.mApp, Constant.Umeng.Send_sms_latlng_phoneisnull);</span> <span class="hljs-keyword">return</span>; } String SENT = <span class="hljs-string">"sms_sent"</span>; String DELIVERED = <span class="hljs-string">"sms_delivered"</span>; PendingIntent sentPI = PendingIntent.getActivity(<span class="hljs-keyword">this</span>, <span class="hljs-number">0</span>, <span class="hljs-keyword">new</span> Intent(SENT), <span class="hljs-number">0</span>); PendingIntent deliveredPI = PendingIntent.getActivity(<span class="hljs-keyword">this</span>, <span class="hljs-number">0</span>, <span class="hljs-keyword">new</span> Intent(DELIVERED), <span class="hljs-number">0</span>); registerReceiver(<span class="hljs-keyword">new</span> BroadcastReceiver() { <span class="hljs-meta">@Override</span> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onReceive</span><span class="hljs-params">(Context context, Intent intent)</span> </span>{ <span class="hljs-keyword">switch</span> (getResultCode()) { <span class="hljs-keyword">case</span> Activity.RESULT_OK: <span class="hljs-comment">// // MobclickAgent.onEvent(E7App.mApp, Constant.Umeng.Send_sms_latlng_success);</span> <span class="hljs-keyword">break</span>; <span class="hljs-keyword">case</span> SmsManager.RESULT_ERROR_GENERIC_FAILURE: <span class="hljs-keyword">case</span> SmsManager.RESULT_ERROR_NO_SERVICE: <span class="hljs-keyword">case</span> SmsManager.RESULT_ERROR_NULL_PDU: <span class="hljs-keyword">case</span> SmsManager.RESULT_ERROR_RADIO_OFF: <span class="hljs-keyword">default</span>: <span class="hljs-comment">// // CrashReport.postCatchedException(new Throwable(getResultData() + getResultCode()));</span> <span class="hljs-keyword">break</span>; } } }, <span class="hljs-keyword">new</span> IntentFilter(SENT)); registerReceiver(<span class="hljs-keyword">new</span> BroadcastReceiver() { <span class="hljs-meta">@Override</span> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onReceive</span><span class="hljs-params">(Context context, Intent intent)</span> </span>{ <span class="hljs-keyword">switch</span> (getResultCode()) { <span class="hljs-keyword">case</span> Activity.RESULT_OK: <span class="hljs-comment">// // MobclickAgent.onEvent(E7App.mApp, Constant.Umeng.Send_sms_latlng_success);</span> <span class="hljs-keyword">break</span>; <span class="hljs-keyword">case</span> Activity.RESULT_CANCELED: <span class="hljs-keyword">default</span>: <span class="hljs-comment">// // CrashReport.postCatchedException(new Throwable(getResultData() + getResultCode()));</span> <span class="hljs-keyword">break</span>; } } }, <span class="hljs-keyword">new</span> IntentFilter(DELIVERED)); SmsManager smsm = SmsManager.getDefault(); <span class="hljs-keyword">if</span>(Build.VERSION.SDK_INT >= <span class="hljs-number">22</span>) { <span class="hljs-keyword">try</span> { List<SubscriptionInfo> mSubInfoList = SubscriptionManager.from(<span class="hljs-keyword">this</span>).getActiveSubscriptionInfoList(); <span class="hljs-keyword">int</span> mSubCount = (mSubInfoList != <span class="hljs-keyword">null</span> && !mSubInfoList.isEmpty()) ? mSubInfoList.size() : <span class="hljs-number">0</span>; <span class="hljs-keyword">int</span> subId = -<span class="hljs-number">1</span>; <span class="hljs-keyword">if</span> (mSubCount != <span class="hljs-number">0</span>) { subId = (<span class="hljs-keyword">int</span>) mSubInfoList.get(<span class="hljs-number">0</span>).getSubscriptionId(); } smsm = SmsManager.getSmsManagerForSubscriptionId(subId); } <span class="hljs-keyword">catch</span> (Throwable e) { e.printStackTrace(); <span class="hljs-comment">// // CrashReport.postCatchedException(e);</span> } } <span class="hljs-keyword">try</span> { <span class="hljs-keyword">if</span> (message.length() > <span class="hljs-number">70</span>) { ArrayList<String> msgs = smsm.divideMessage(message); ArrayList<PendingIntent> sentIntents = <span class="hljs-keyword">new</span> ArrayList<PendingIntent>(); <span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>;i<msgs.size();i++){ sentIntents.add(sentPI); } smsm.sendMultipartTextMessage(phoneNum, <span class="hljs-keyword">null</span>, msgs, sentIntents, <span class="hljs-keyword">null</span>); } <span class="hljs-keyword">else</span> { smsm.sendTextMessage(phoneNum, <span class="hljs-keyword">null</span>, message, sentPI, deliveredPI); } <span class="hljs-comment">// smsm.sendTextMessage(phoneNum, null, message, sentPI, deliveredPI);</span> } <span class="hljs-keyword">catch</span> (Throwable e) { System.out.println(<span class="hljs-string">"-------------"</span> + e.getMessage()); e.printStackTrace(); <span class="hljs-comment">// // CrashReport.postCatchedException(e);</span> } } |
参考之前文章:8.【小萌伴Android】手电筒功能及其实现
注意:该功能需要另一台手机的辅助,才能找到手机(后面即将介绍的语音找手机则不需要另一台手机辅助)
简书:ThinkinLiu 博客: IT老五

相关内容:
【小萌伴Android】相关文章目录
1.【小萌伴Android】思量再三,终于鼓起勇气开源~
2.【小萌伴Android】机器人陪聊模块分享
3.【小萌伴Android】新闻/H5游戏模块及广告过滤
4.【小萌伴Android】段子趣图模块及其实现 及 段子趣图数据爬取
5.【小萌伴Android】原生小游戏及其实现(一)2048
6.【小萌伴Android】原生小游戏及其实现(二)小鸟
7.【小萌伴Android】原生小游戏及其实现(三)飞机
8.【小萌伴Android】手电筒功能及其实现
9.【小萌伴Android】机器人陪聊--语音功能及其实现
10.【小萌伴Android】短信找手机功能及其实现