应用被杀死后无法接收SIP电话

3

即使应用程序在后台、退出或重新启动时,我应该怎么做才能接收SIP电话呢? 目前我们正在运行一个前台服务,并使用粘性通知与我们的SIP服务器保持连接。但这种解决方案并不完全可行。 请帮我实现这一点,提前致谢!

3个回答

2
首先,您需要一个永不停止的主服务(即使设备启动,也要借助启动接收器)。您必须在MainService中初始化sip管理器、sip配置文件和呼叫相关代码,而不是在MainActivity中。
然后,您需要一个广播接收器来接收SIP呼入。请参考以下示例: public class YourReceiver extends 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呼叫由YourReceiver接收并分配给MainService.call,以便MainService可以进行进一步的处理。

        mainService.call = incomingCall;

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

}


1
为了让一个服务持续运行,可以启动一个任务调度器,将该任务设为 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;
    }
}

在您的项目中创建一个继承自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;
    }

}

最后,添加一个BootUpReceiver以在手机重新启动时自动启动通知和服务。它应该具有权限。
 <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>

0

运行服务是正确的方法。您只需启动处理来自服务的传入呼叫的活动。然后,该活动可以绑定到您的服务并请求所有需要接管呼叫的内容。这实际上就是您所需要的全部。


服务没有在后台持续运行。因此,我没有收到 SIP 电话的回调。 - HrushiKesava Reddy Penugonda

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接