简体   繁体   English

应用程序被杀时无法接收SIP呼叫

[英]Unable to receive SIP calls when app is killed

What should I do to receive SIP calls even when app is in background, exits or restarts? 即使应用程序处于后台,退出或重新启动,我该怎么做才能接收SIP呼叫? Currently we're running a foreground service with sticky notification to keep connected with our sip server. 目前我们正在运行带有粘性通知的前台服务,以便与我们的SIP服务器保持连接。 This solution isn't completely working Please help me to achieve this, Thanks in advance! 这个解决方案还没有完全正常工作请帮我实现这个,提前谢谢!

Firstly, you want a Mainservice that never stops (Even when the device booted, with the help of a bootup receiver). 首先,您需要一个永不停止的Mainservice(即使设备在启动接收器的帮助下启动)。 You have to initialise your sip manager, sip profile and call related codes in the MainService and not in the MainActivity. 您必须初始化您的sip管理器,sip配置文件并在MainService中调用相关代码,而不是在MainActivity中。

Then, You need a BroadCast receiver that receives incoming sip calls. 然后,您需要一个接收传入SIP呼叫的BroadCast接收器。 see below example, 见下面的例子,

public class YourReceiver extends BroadcastReceiver { 公共类YourReceiver扩展BroadcastReceiver {

SipAudioCall incomingCall   = null;
private static YourReceiver instance;
MainService mainService;
public Intent incomingCallIntent;

public static YourReceiver getInstance() {
    return instance;
}

/**
 * Processes the incoming call, answers it, and hands it over to the
 * MainActivity.
 * @param context The context under which the receiver is running.
 * @param intent The intent being received.
 */
@Override
public void onReceive(final Context context, Intent intent) {
    Log.i(TAG, "onReceive: ");
    instance    = this;
    mainService = MainService.getInstance();

    try {
        SipAudioCall.Listener listener = new SipAudioCall.Listener() {
            @Override
            public void onRinging(SipAudioCall call, SipProfile caller) {
                Log.i(TAG, "onRinging: ");


            }

            // extra added
            @Override
            public void onRingingBack(SipAudioCall call) {
                Log.i(TAG, "onRingingBack: ");
                super.onRingingBack(call);
            }

            @Override
            public void onReadyToCall(SipAudioCall call) {
                Log.i(TAG, "onReadyToCall: ");
                super.onReadyToCall(call);
            }

            @Override
            public void onError(SipAudioCall call, int errorCode, String errorMessage) {
                Log.e(TAG, "onError: errorCode = " + errorCode + ", errorMessage = " + errorMessage);
                super.onError(call, errorCode, errorMessage);
            }

            @Override
            public void onChanged(SipAudioCall call) {
                Log.i(TAG, "onChanged: ");
                super.onChanged(call);
            }

            @Override
            public void onCalling(SipAudioCall call) {
                Log.i(TAG, "onCalling: ");
                super.onCalling(call);
            }

            @Override
            public void onCallHeld(SipAudioCall call) {
                Log.i(TAG, "onCallHeld: ");
                super.onCallHeld(call);
            }

            @Override
            public void onCallBusy(SipAudioCall call) {
                Log.i(TAG, "onCallBusy: ");
                super.onCallBusy(call);
            }

            @Override
            public void onCallEnded(SipAudioCall call) {
                Log.i(TAG, "onCallEnded: ");


            }

            @Override
            public void onCallEstablished(SipAudioCall call) {
                Log.i(TAG, "onCallEstablished: ");
                super.onCallEstablished(call);
            }
        };


        mainService  = MainService.getInstance();
        incomingCall = mainService.manager.takeAudioCall(intent,listener);
        if(mainService.manager.isIncomingCallIntent(intent)){
            incomingCallIntent = intent;
        }

        //starting call screen activity when the receiver receives incoming call
        Intent i    = new Intent(context, CallActivity.class);
        i.putExtra("name", peerName);
        i.putExtra("number", peerNumber);
        i.putExtra("callType", "Incoming");
        context.startActivity(i);

//Sip call received by YourReceiver is assigned to MainService.call so that the MainService can do the further processes. //将YourReceiver收到的SIP调用分配给MainService.call,以便MainService可以执行进一步的处理。

        mainService.call = incomingCall;

    } catch (Exception e) {
        if (incomingCall != null) {
            incomingCall.close();
        }
    }
}

} }

Running a service is the right way. 运行服务是正确的方法。 You just have to start the activity which will handle your incoming call from the service. 您只需启动将处理来自服务的来电的活动。 The activity can then bind to your service and request all it needs to take over the call. 然后,活动可以绑定到您的服务并请求接管呼叫所需的全部内容。 That's actually all you need. 这实际上就是你所需要的一切。

For making a Service run continuously, start a Job scheduler to make this job be a part of android system jobs. 要使服务连续运行,请启动Job scheduler以使此作业成为android系统作业的一部分。

package com.xxx;

import android.app.job.JobParameters;
import android.app.job.JobService;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.util.Log;

import androidx.annotation.RequiresApi;

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class XXJobService extends JobService {
    private String TAG = "XXJobService";
    private Context context;

    public XXJobService() {
    }

    @Override
    public boolean onStartJob(JobParameters params) {
        context = this;

        try {
            if (!MyApp.isServiceRunning(context, MainService.class.getName())) {
                Log.i(TAG, "onStartJob : MainService not running so start");

                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    context.getApplicationContext()
                            .startForegroundService(new Intent(context, MainService.class)
                                    .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP));
                } else {
                    context.getApplicationContext()
                            .startService(new Intent(context, MainService.class)
                                    .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP));
                }
            }
        } catch (Exception e) {
            Log.e(TAG, "Exception - MainService not running: " + e.getLocalizedMessage());
        }


        Log.i(TAG, "onStartJob, returnValue = " + returnValue);
        return returnValue;
    }

    @Override
    public boolean onStopJob(JobParameters params) {

        boolean returnValue = true;

        Log.i(TAG, "onStopJob, returnValue = " + returnValue);
        return returnValue;
    }
}

Create an Application class in your project that extends Application and define it in your manifest also. 在项目中创建一个扩展Application的Application类,并在清单中定义它。

import android.app.ActivityManager;
import android.app.Application;
import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.util.Log;
import java.util.Arrays;
import java.util.List;

public class MyApp extends Application {

    Context context;
    private static MyApp instance;
    static String TAG = "MyApp";
    MainService mainService;
    JobScheduler jobScheduler;
    private static final int JOB_ID = 1;

    public static MyApp getInstance() {
        return instance;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        context  = this;
        instance = this;
        Log.i(TAG, "onCreate: ");

        // Job scheduler for android version Lolipop(Android 5.0) and above
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            try {
                jobScheduler             = (JobScheduler) getSystemService(JOB_SCHEDULER_SERVICE);
                ComponentName jobService = new ComponentName(getPackageName(), XXJobService.class.getName());
                Log.e(TAG, "onCreate: ComponentName : " + jobService );
                JobInfo jobInfo          = new JobInfo.Builder(JOB_ID, jobService)
                        .setPersisted(true)
                        .setPeriodic(5000)
                        .build();
                int jobId                = jobScheduler.schedule(jobInfo);

                if (jobId == JobScheduler.RESULT_SUCCESS) {
                    Log.e(TAG, "JobScheduler RESULT_SUCCESS");
                    // Toast.makeText(context, "Successfully scheduled job : " + jobId, Toast.LENGTH_SHORT).show();
                } else {
                    Log.e(TAG, "JobScheduler RESULT_FAILURE: " + jobId);
                    // Toast.makeText(context, "RESULT_FAILURE: " + jobId, Toast.LENGTH_SHORT).show();
                }
            } catch (Exception e) {
                Log.e(TAG, "JobScheduler Exception : " + e.getLocalizedMessage());
            }
        }

        if (!isServiceRunning(context, MainService.class.getName())) {
            try {
                Intent intent = new Intent(context, MainService.class);

                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    startForegroundService(intent);
                } else {
                    startService(intent);
                }
            } catch (Exception e) {
                Log.e(TAG, "Exception startService : " + e.getLocalizedMessage());
            }
        }

        mainService = MainService.getInstance();
        Log.e(TAG," MainSerivice : " + mainService);

        Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread t, Throwable e) {
                handleUncaughtException(t, e);
            }
        });
    }


    public static boolean isServiceRunning(Context context, String serviceClassName) {
        if (context == null || serviceClassName.equalsIgnoreCase("")) {
            Log.i(TAG, "isServiceRunning called with context = null or service name blank");
            return false;
        }

        ActivityManager activityManager                     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningServiceInfo> services   = activityManager.getRunningServices(Integer.MAX_VALUE);

        for (ActivityManager.RunningServiceInfo runningServiceInfo : services) {
            if (runningServiceInfo.service.getClassName().equals(serviceClassName))
                return true;
        }

        return false;
    }

}

Finally, put a BootUpReceiver to automatically start the notofication and services whenever the phone is restarted. 最后,将BootUpReceiver置于手机重启时自动启动通知和服务。 It should have the permission 它应该有权限

 <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />


<receiver
            android:name=".StartupReceiver"
            android:enabled="true">
            <intent-filter>
                <action android:name="com.xx.MainService" />
                <action android:name="android.intent.action.ACTION_SHUTDOWN" />
                <action android:name="android.intent.action.BOOT_COMPLETED" />
                <action android:name="android.intent.action.QUICKBOOT_POWERON" />

                <category android:name="android.intent.category.HOME" />
            </intent-filter>
        </receiver>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 应用程式被杀死时,Android无法接收到解析推送通知 - Unable tor receive parse push notifications when app is killed Android 使用 FCM 杀死应用程序时,Android 无法接收通知 - Android unable to receive notification when app is killed using FCM 应用被杀死时接收PubNub推送通知 - Receive PubNub Push Notifications when app is killed 应用被杀死时接收Fence回调 - Receive Fence callbacks when app is killed 当我收到应用程序 OTA 更新时,我的应用程序会被终止吗? - Will my app get killed when i receive app OTA updates? 应用程序被杀死时无法处理 FCM 消息 - FCM messages unable to be handled when app is killed 即使应用被杀死,如何继续接收地理围栏通知? - How to receive continuous geofence notifications even when app is killed? Firebase云消息传递服务 - 即使应用程序被终止也会收到通知 - Firebase Cloud Messaging Service - Receive Notifications even when app is killed 应用程序被杀死时是否可以接收 FCM 推送通知? - Is it possible to receive FCM push notifications when app is killed? 在Android上杀死应用时收到系统托盘通知 - Receive system tray notification when app killed on Android
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM