我正在尝试使用不可阻挡的后台服务,以便每次都可以在警报对话框中获取新呼叫的呼叫详细信息,并通过警报对话框通知用户。问题是关闭应用程序后停止服务。我不完全确定我的错误。
我已经在手机上测试过,即使关闭了应用程序也能正常运行
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.jenya1.didbizdialer">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
<uses-permission android:name="android.permission.ACTION_MANAGE_OVERLAY_PERMISSION" />
<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.NoActionBar">
<activity android:name=".activity.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".activity.DialerActivity"></activity>
<service android:name=".service.PhoneCallStatesService"
android:stopWithTask="false" />
<receiver android:name=".service.ReceiverCall">
<intent-filter>
<action android:name="com.android.techtrainner" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
BootReceiver 应启动服务
public class ReceiverCall extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.i("Service Stops", "Ohhhhhhh");
context.startService(new Intent(context, PhoneCallStatesService.class));;
}
}
服务 PhoneCallStatesService 设置为显示呼叫详细信息对话框
public class PhoneCallStatesService extends Service {
private static final String TAG = PhoneCallStatesService.class.getSimpleName();
private TelephonyManager telephonyManager;
private PhoneStateListener listener;
private boolean isOnCall;
private static boolean isIncoming;
private static int lastState = TelephonyManager.CALL_STATE_IDLE;
private static Date callStartTime;
private static String savedNumber; //because the passed incoming is only valid in ringing
public IBinder onBind(Intent arg0) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
showToast("service started");
isOnCall = false;
telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
}
protected BroadcastReceiver stopReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "received stop broadcast");
}
};
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
listener = new PhoneStateListener() {
@Override
public void onCallStateChanged(int state, String incomingNumber) {
if(lastState == state){
//No change, debounce extras
return;
}
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
if(lastState == TelephonyManager.CALL_STATE_RINGING){
//Ring but no pickup- a miss
onMissedCall(getApplicationContext(), savedNumber, callStartTime);
}
else if(isIncoming){
onIncomingCallEnded(getApplicationContext(), savedNumber, callStartTime, new Date());
}
else{
onOutgoingCallEnded(getApplicationContext(), savedNumber, callStartTime, new Date());
}
if (isOnCall) {
showToast("Call state: idle");
isOnCall = false;
}
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
if(lastState != TelephonyManager.CALL_STATE_RINGING){
isIncoming = false;
callStartTime = new Date();
showToast("Outgoing start ");
onOutgoingCallStarted(getApplicationContext(), savedNumber, callStartTime);
}
else
{
isIncoming = true;
callStartTime = new Date();
showToast("Incoming answered ");
onIncomingCallAnswered(getApplicationContext(), savedNumber, callStartTime);
}
isOnCall = true;
break;
case TelephonyManager.CALL_STATE_RINGING:
isIncoming = true;
callStartTime = new Date();
savedNumber = incomingNumber;
onIncomingCallReceived(getApplicationContext(), incomingNumber, callStartTime);
showToast("call state: ringing");
break;
}
lastState = state;
}
};
// Register the listener with the telephony manager
telephonyManager.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
return START_STICKY;
}
protected void onIncomingCallReceived(Context ctx, String number, Date start)
{
Toast.makeText(ctx, "received", Toast.LENGTH_SHORT).show();
Log.e("received","received");
}
protected void onIncomingCallAnswered(Context ctx, String number, Date start)
{
Toast.makeText(ctx, "upadyo", Toast.LENGTH_SHORT).show();
Log.e("upadyo","upadyo");
}
protected void onIncomingCallEnded(Context ctx, String number, Date start, Date end)
{
Toast.makeText(ctx, "incoming call end", Toast.LENGTH_SHORT).show();
Log.e("incoming call end","incoming call end");
startactivity(ctx);
}
protected void onOutgoingCallStarted(Context ctx, String number, Date start)
{
Toast.makeText(ctx, "outcall call start", Toast.LENGTH_SHORT).show();
Log.e("outcall call start","outcall call start");
}
protected void onOutgoingCallEnded(Context ctx, String number, Date start, Date end)
{
Toast.makeText(ctx, "Outgoing call end", Toast.LENGTH_SHORT).show();
Log.e("Outgoing call end","Outgoing call end");
startactivity(ctx);
}
protected void onMissedCall(Context ctx, String number, Date start)
{
Toast.makeText(ctx, "missed call", Toast.LENGTH_SHORT).show();
Log.e("missed call","missed call");
startactivity(ctx);
}
private void showToast(String msg) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
}
public void startactivity(final Context ctx) {
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(ctx, R.style.myDialog);
LayoutInflater inflater = (LayoutInflater)ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View dialogView = inflater.inflate(R.layout.popupdialog, null);
dialogBuilder.setView(dialogView);
LinearLayout reminder=(LinearLayout)dialogView.findViewById(R.id.lnreminder);
LinearLayout savecontact=(LinearLayout)dialogView.findViewById(R.id.lnsavecontact);
LinearLayout contactblock=(LinearLayout)dialogView.findViewById(R.id.lnspam);
AlertDialog alertDialog = dialogBuilder.create();
WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
lp.copyFrom(alertDialog.getWindow().getAttributes());
lp.width = WindowManager.LayoutParams.MATCH_PARENT;
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
lp.gravity = Gravity.BOTTOM;
lp.windowAnimations = R.style.DialogAnimation;
alertDialog.getWindow().setAttributes(lp);
alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
alertDialog.show();
reminder.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(ctx, "reminder", Toast.LENGTH_SHORT).show();
}
});
savecontact.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(ctx, "Saved", Toast.LENGTH_SHORT).show();
}
});
contactblock.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(ctx, "block", Toast.LENGTH_SHORT).show();
}
});
}
@Override
public void onDestroy() {
try{
if(stopReceiver!=null)
unregisterReceiver(stopReceiver);
stopSelf();
}catch(Exception e)
{
Log.e("Service Destroy Error",e.getMessage());
}
}
}
任何帮助或示例都将受到高度赞赏
答案 0 :(得分:1)
在Redmi设备中,关闭应用程序后服务会被杀死,尽管您已经编写了所有代码以在杀死应用程序后重新启动它。您需要为此特定应用启用自动启动。 像WhatsApp等应用程序运行他们的服务是因为他们用小米标记了他们的应用程序。但我们不能这样做。 或者您可以使用JobScheduler或AlarmManager来运行服务。