目前我正在开发像Truecaller这样的呼叫拦截器应用程序。
我需要什么
即使我的应用已从中移除,我也想检测来电 最近的应用列表。
Manifest.xml代码
<receiver android:name=".PhoneStateReceiver">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
我的广播接收器代码
@Override
public void onReceive(Context context, Intent intent) {
//my call blocking code
}
我的问题
我的BroadcastReceiver无法在后台工作,就像我从中移除一样 最近的应用列表。
我的完整清单代码
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="ranjith.callblocker">
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.GET_TASKS" />
<application
android:allowBackup="true"
android:enabled="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<receiver
android:name=".PhoneStateReceiver"
android:enabled="true"
android:exported="true"
android:process=":anotherProcess">
<intent-filter android:priority="1000">
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
我应该使用服务还是其他什么?
更新
在Suraj的回答中,我在接收器中尝试了这个标签
android:enabled="true"
android:exported="true"
android:process=":anotherProcess"
适用于kitkat .. 但不适用于棒棒糖..
更新了问题:
Incase如果无法保持活动广播接收器即使我的应用已关闭,我如何检测来电?
任何人给出详细的答案..
答案 0 :(得分:2)
我们在这里通知接收方服务。
所以将服务类改为
public class MyService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
new CountDownTimer(100000,4000)
{
@Override
public void onTick(long millisUntilFinished) {
sendBroadcast(new Intent("fromservice"));
}
@Override
public void onFinish() {
}
}.start();
return START_STICKY;
}
}
现在将接收器设为
public class MyReceiver extends WakefulBroadcastReceiver {
@Override
public void onReceive(final Context context, Intent intent) {
Toast.makeText(context, "inside receiver", Toast.LENGTH_SHORT).show();
}
}
现在从主要活动
启动服务 public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startService(new Intent(this,MyService.class));
}
}
在清单中声明接收者和服务如下
<receiver android:name=".MyReceiver"
android:process=":jk"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="fromservice"/>
</intent-filter>
</receiver>
<service android:name=".MyService"
android:process=":ff"
android:enabled="true"
android:exported="true" />
将以下权限添加到清单中。 这用于防止cpu睡眠。
<uses-permission android:name="android.permission.WAKE_LOCK"/>
什么是倒计时器?
倒计时器可以被理解为具有方法
的迭代onTick()和onFinish()
在CountDownTimer构造函数中给出的间隔(持续时间)之后多次调用onTick()。
当longTimeInFuture已经过时,onFinish()最后被调用(只有一次)。
答案 1 :(得分:2)
您需要创建一个Service
并在清单中注册它。之后,您应该在服务中注册BroadcastReceiver
而不是清单。
当app从最近移除时,Service
未停止,因此您的接收器也将继续工作。当应用程序从最近删除时,您甚至还会通过Service#onTaskRemoved
收到回电。
虽然您还需要处理其他一些情况,但可以停止Service
。
有一种情况是,当系统内存不足时,android可以停止服务,您可以通过从START_STICKY
方法返回onStartCommand
来修复它。
其他情况是当设备重新启动时,您需要在mnifest中为ACTION_BOOT_COMPLETED
注册广播接收器以解决此问题。您可以使用onReceive
方法重新启动服务。
希望下面的示例代码有帮助 -
private BroadcastReceiver mReceiver;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.v(LOG_TAG, "worked");
}
};
registerReceiver(mReceiver,
new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
return START_STICKY;
}
@Override
public void onDestroy() {
unregisterReceiver(mReceiver);
super.onDestroy()
}
答案 2 :(得分:0)
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.phonestatelistener">
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<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="com.android.receiver.PhoneStateListener" android:exported="true" >
<intent-filter >
<action android:name="android.intent.action.PHONE_STATE"/>
<action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>
</application>
public class PhoneStateListener extends BroadcastReceiver {
public static String TAG="PhoneStateListener";
public static String ACTION_PHONE_STATE = "android.intent.action.PHONE_STATE";
public static String ACTION_OUTGOING_CALL = "android.intent.action.NEW_OUTGOING_CALL";
public static String ACTION_SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION_PHONE_STATE)) {
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
Toast.makeText(context, "Incoming call", Toast.LENGTH_SHORT).show();
Log.d(TAG, "Incoming call");
}
} else if (intent.getAction().equals(ACTION_OUTGOING_CALL)) {
Toast.makeText(context, "Outgoing call", Toast.LENGTH_SHORT).show();
Log.d(TAG, "Outgoing call");
} else if (intent.getAction().equals(ACTION_SMS_RECEIVED)) {
Toast.makeText(context, "Incoming message", Toast.LENGTH_SHORT).show();
Log.d(TAG, "Incoming message");
}
}
}
试试这个。它会一直有效,直到您强行关闭应用程序
答案 3 :(得分:0)
您可以尝试在onCreate()活动中注册广播接收器。
答案 4 :(得分:0)
这是代码它适用于我:
在Manifest中添加权限:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
后续步骤在启动应用时创建Service
启动(可能是MainActivity
)
在onCreate
Service
中调用此代码
代码
((TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE)).listen(new PhoneStateListener(new PhoneStateListener.PhoneCallListener() {
@Override
public void PhoneCall() {
// Do something
}
@Override
public void PhoneOff() {
// Do something
}
@Override
public void MissCall() {
// Do something
}
}), PhoneStateListener.LISTEN_CALL_STATE);
PhoneStateListener.java
import android.telephony.TelephonyManager;
/**
* PhoneStateListener.
*
* @author DaoLQ
*/
public class PhoneStateListener extends android.telephony.PhoneStateListener {
public interface PhoneCallListener {
void PhoneCall();
void PhoneOff();
void MissCall();
}
private PhoneCallListener mPhoneCallListener;
private boolean ring = false;
private boolean callReceived = false;
public PhoneStateListener(PhoneCallListener listener) {
mPhoneCallListener = listener;
}
@Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
mPhoneCallListener.PhoneOff();
if (ring && !callReceived) {
mPhoneCallListener.MissCall();
}
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
// CALL_STATE_OFFHOOK;
callReceived = true;
mPhoneCallListener.PhoneCall();
break;
case TelephonyManager.CALL_STATE_RINGING:
ring = true;
mPhoneCallListener.PhoneCall();
break;
default:
break;
}
}
}
答案 5 :(得分:-1)
这是我的食谱,实际上是从4.4到6.0
清单:
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<application>
<receiver android:name=".utils.PhoneReceiver">
<intent-filter android:priority="999">
<action android:name="android.intent.action.PHONE_STATE" />
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
<action android:name="android.intent.action.NEW_OUTGOING_CALL" />
</intent-filter>
</receiver>
</application>
然后在PhoneReceiver.class
中public class PhoneReceiver extends BroadcastReceiver
{
public void onReceive(Context thecontext, Intent intent)
{
if ("android.provider.Telephony.SMS_RECEIVED".equals(intent.getAction()))
{
// handle SMS received
}
else if ("android.intent.action.NEW_OUTGOING_CALL".equals(intent.getAction()))
{
// handle outgoing call
}
else if (intent.getAction().equals("android.intent.action.PHONE_STATE"))
{
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
/* from there do your stuff... */
if (state.equals(TelephonyManager.EXTRA_STATE_RINGING))
String incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
/* etc. etc. */
}
}
}
答案 6 :(得分:-2)
您必须从清单
添加权限<uses-permission android:name="android.permission.READ_PHONE_STATE" >
接收方必须具有声明的以下属性,并且在声明名称时也始终尝试使用完整的包名称。
<receiver
android:name="ranjith.callblocker.PhoneStateReceiver"
android:enabled="true"
android:exported="true"
android:permission="android.permission.READ_PHONE_STATE">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
然后尝试将Log放入接收器块,
@Override
public void onReceive(Context context, Intent intent) {
Log.i("TAG", "Receiver is called but might not block call for other reason!");
}
确保您不是通过名字从任何人onPause,onStop,onDestroy方法取消注册接收者