我长期以来一直面临着这个问题。每个人都会向你提供一个指向Google开发者网站的链接,其中仅描述了他们对后台服务有限制的情况,没有适当的文档,也没有示例代码向开发者展示如何在Oreo或更高版本上实现它。即使在Stack Overflow上,您也只会找到有关Google开发人员网站限制的链接。
我希望您或其他开发人员会觉得这非常有帮助。
仍然存在一些排除项,例如
NEW_OUTGOING_CALL
或
BOOT_COMPLETED
,您仍然可以在清单中使用。但是,在应用程序上下文中实现运行时是一个好习惯。我希望我的
PHONE_STATE
始终准备好接收来电和去电,即使在每次重新启动时...
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.rushi.boottest">
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="26" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<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/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=".MyReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<service
android:name=".CatchNumbers"
android:enabled="true"
android:exported="true" />
<service
android:name=".WatchMan"
android:enabled="true"
android:exported="true"></service>
</application>
</manifest>
在上面的 manifest.xml 文件中,我没有放置 WRITE_EXTERNAL_STORAGE
和 READ_EXTERNAL_STORAGE
。因为我在运行时实现了它,所以它会被 Android Studio 自动插入。
这是我的 OnBoot 接收器:
package com.example.rushi.boottest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.util.Log;
import android.widget.Toast;
public class MyReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
Log.d("BootTest : ", "\nOnBootReceiver - Received a broadcast!");
Toast.makeText(context, "OnBootReceiver Received a broadcast!!", Toast.LENGTH_LONG).show();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
context.startForegroundService(new Intent(context, WatchMan.class));
}
else
{
context.startService(new Intent(context, WatchMan.class));
}
}
}
这里有一个叫做WatchMan.java的前台服务,它实现了运行时接收器。
public class WatchMan extends Service
{
NotificationManager mNotifyManager;
NotificationCompat.Builder mBuilder;
NotificationChannel notificationChannel;
String NOTIFICATION_CHANNEL_ID = "17";
private BroadcastReceiver mCallBroadcastReceiver = new BroadcastReceiver()
{
@Override
public void onReceive(Context context, Intent intent)
{
String PhoneNumber = "UNKNOWN";
Log.d("RECEIVER : ","IS UP AGAIN....");
try
{
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
if(state == null)
{
PhoneNumber = "UNKNOWN";
}
else if (state.equals(TelephonyManager.EXTRA_STATE_RINGING))
{
PhoneNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
Log.d("RECEIVER : ","Incoming number : "+PhoneNumber);
}
if(intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL"))
{
PhoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
Log.d("RECEIVER : ","Outgoing number : "+PhoneNumber);
}
if(!PhoneNumber.contentEquals("UNKNOWN"))
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
context.startForegroundService(new Intent(context, CatchNumbers.class));
}
else
{
context.startService(new Intent(context, CatchNumbers.class));
}
}
}
catch (Exception e)
{
e.printStackTrace();
Log.e("RECEIVER : ", "Exception is : ", e);
}
}
};
public WatchMan() { }
@Override
public void onCreate()
{
super.onCreate();
Log.d("WatchMan : ", "\nOnCreate...");
IntentFilter CallFilter = new IntentFilter();
CallFilter.addAction("android.intent.action.NEW_OUTGOING_CALL");
CallFilter.addAction("android.intent.action.PHONE_STATE");
this.registerReceiver(mCallBroadcastReceiver, CallFilter);
Log.d("WatchMan : ", "\nmCallBroadcastReceiver Created....");
mNotifyManager = (NotificationManager) getApplicationContext().getSystemService(NOTIFICATION_SERVICE);
mBuilder = new NotificationCompat.Builder(this, null);
mBuilder.setContentTitle("Insta Promo")
.setContentText("Checking New Numbers")
.setTicker("Checking New Numbers")
.setSmallIcon(R.drawable.ic_launcher_background)
.setPriority(Notification.PRIORITY_LOW)
.setDefaults(Notification.DEFAULT_ALL)
.setVisibility(Notification.VISIBILITY_PUBLIC)
.setOngoing(true)
.setAutoCancel(false);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "My Notifications", NotificationManager.IMPORTANCE_HIGH);
notificationChannel.setDescription("Channel description");
notificationChannel.enableLights(true);
notificationChannel.setLightColor(Color.RED);
notificationChannel.setVibrationPattern(new long[]{0, 1000, 500, 1000});
notificationChannel.enableVibration(true);
notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
mNotifyManager.createNotificationChannel(notificationChannel);
mBuilder.setChannelId(NOTIFICATION_CHANNEL_ID);
startForeground(17, mBuilder.build());
}
else
{
mBuilder.setChannelId(NOTIFICATION_CHANNEL_ID);
mNotifyManager.notify(17, mBuilder.build());
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
Log.d("WatchMan : ", "\nmCallBroadcastReceiver Listening....");
return START_NOT_STICKY;
}
@Override
public void onDestroy()
{
this.unregisterReceiver(mCallBroadcastReceiver);
Log.d("WatchMan : ", "\nDestroyed....");
Log.d("WatchMan : ", "\nWill be created again....");
}
@Override
public IBinder onBind(Intent intent)
{
throw new UnsupportedOperationException("Not yet implemented");
}
}
现在,在调用之前将电话号码插入到sqlite
数据库表中;这样您就可以从CatchNumbers.java服务中读取它,并对进出的数字执行任何操作。希望它能帮助你或其他人。