您当前的位置: 首页 > 学无止境 > 心得笔记 网站首页心得笔记
59_广播接受者的类型&实现自动ip拨号
发布时间:2021-03-05 15:32:15编辑:雪饮阅读()
通过代码注册广播接收者
<intent-filter android:priority="1000">
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
AndroidManifest.xml:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="注册广播接收者"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:onClick="register"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.smslistenercode">
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.SmsListenerCode">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>MainActivity.java:
package com.example.smslistenercode;
import androidx.appcompat.app.AppCompatActivity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void register(View view){
IntentFilter filter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
SmsReceiver receiver = new SmsReceiver();
registerReceiver(receiver, filter);
}
class SmsReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
System.out.println("接收到了广播");
}
}
}部署到设备中当其它设备给他发短信就被监听到了
但是这种通过代码进行注册的方式,这个应用程序进程被杀死。那么注册的广播接收者也就随之而失效。
要说杀死呢,像是这样,将这个项目上划就杀死了其进程。
广播的分类
有序广播
像是短信到来的广播、电话拨打的广播这类都属于是有序的广播。
有序的广播在接收者优先级从高到底进行依次传递,当某个高优先级的接收者执行abortBroadcast()方法可以终止广播事件,则低优先级的接收者将不在接收得到。
无序广播.
没有优先级 任何人 注册广播接受者的人,都可以接收到广播.
没有abortboradcast()方法
有序广播与无序广播的发送
sendBroadcast(intent); // 发送一条广播
sendOrderedBroadcast(intent, receiverPermission); // 发送一条有序广播
有序广播指定接收者
sendOrderedBroadcast(intent, receiverPermission, resultReceiver, scheduler, initialCode, initialData, initialExtras)
如果发送广播的时候 使用的 上面的api发送出去的广播
第三个参数 resultReceiver 指定了广播的接受者
即便是中间我把广播给终止 abortbroadcast()
resultReceiver 还是会接受到广播事件
有序广播
建立一个项目捕获系统拨号键盘拨出的电话,则有:
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>MainActivity.xml:
package com.example.ipphone;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.ipphone">
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.IpPhone">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".OutGoingCallReceiver" >
<intent-filter android:priority="1000">
<action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
</intent-filter>
</receiver>
</application>
</manifest>建立OutGoingCallReceiver.java于MainActivity.java同目录
package com.example.ipphone;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class OutGoingCallReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
System.out.println("接收到拨号键盘打出的电话"+getResultData());
}
}然后部署到设备通过拨号键盘拨出的电话号码就被接收获取了
这个时候将OutGoingCallReceiver.java修改为:
package com.example.ipphone;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class OutGoingCallReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
System.out.println("接收到拨号键盘打出的电话"+getResultData());
abortBroadcast();
}
}这里虽然终止了广播,但是实际并没有生效,因为这个电话拨出功能是显式指定了接收者。
中间人攻击
像是上面,我们无法终止广播的传递,当该广播显式指定了接收者的时候。但是如果OutGoingCallReceiver.java修改如:
package com.example.ipphone;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class OutGoingCallReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
System.out.println("接收到拨号键盘打出的电话"+getResultData());
setResultData("999");
}
}部署到设备上并结合日志猫,可以看出,我们拨出的电话虽然是110,但实际上打到了999上
像是这种我们虽然无法终止广播传递,但是可以修改广播内容后,让它继续传递给原本的目标的手段叫做中间人攻击。
终止广播
虽然显式指定了接收者的广播不可以被终止,但是利用中间人的原理也可以伪终止,比如OutGoingCallReceiver.java修改为:
package com.example.ipphone;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class OutGoingCallReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
System.out.println("接收到拨号键盘打出的电话"+getResultData());
setResultData(null);
}
}这里将数据篡改为null,那么拨号键盘拨出去就会直接闪退了(某些特殊号码除外,像是112之类,可能系统做了某些处理)
ip电话
利用上面中间人攻击的原理,及其项目则我们可以稍微改造下就能实现ip电话的功能。
所谓的ip电话就是比如你拨出的电话号码是13916354914,那么ip号码若是110,则会在呼叫界面显示的是加了前缀的电话号码,即11013916354914.
那么主要修改这几处即可
MainActivity.java:
package com.example.ipphone;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void click(View view){
EditText et = (EditText) this.findViewById(R.id.et_ipnumber);
String ipnumber = et.getText().toString().trim();
//存储ip号码(拨出号码时自动加上的前缀)于SharedPreferences中
SharedPreferences sp = getSharedPreferences("config", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
editor.putString("ipnumber", ipnumber);
editor.commit();
}
}OutGoingCallReceiver.java:
package com.example.ipphone;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
public class OutGoingCallReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
System.out.println("接收到拨号键盘打出的电话"+getResultData());
//从SharedPreferences中获取存储的ip号码
SharedPreferences sp = context.getSharedPreferences("config", Context.MODE_PRIVATE);
String ipnumber = sp.getString("ipnumber", "");
setResultData(ipnumber+getResultData());
}
}activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
>
<EditText
android:id="@+id/et_ipnumber"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</EditText>
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="设置ip号码"
android:onClick="click"
/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>然后部署到设备中,设置ip号码,这里假如为110
然后回到拨号键盘进行拨号
可以看到前缀110已经自动添加上了
关键字词:广播,android,短信,电话,拨号