[英]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.