无法停止的服务不工作

Unstoppable Service not working

我正在尝试使用不可停止的后台服务,以便每次都能在警报对话框中获取新呼叫的呼叫详细信息,并通过警报对话框通知用户。问题是服务在关闭应用程序后停止。我不完全确定我做错了什么。

我已经在我的 phone 上进行了测试,即使在关闭应用程序后它也能正常工作

<?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());
    }
  }
}

任何帮助或示例将不胜感激

在Redmi设备中,尽管您已经编写了所有代码以在关闭应用程序后重新启动它,但在您关闭应用程序后服务会被终止。您需要为此特定应用启用自动启动。 WhatsApp 等应用程序有他们的服务 运行ning 因为他们已经用小米标记了他们的应用程序。但我们做不到。 或者您可以使用 JobScheduler 或 AlarmManager 来制作您的服务 运行。