JLChen
2021-08-28 27e9f729fa9532ebc22afea84aa80434b8765fa5
HDLLinphoneSDKDemoNew/HDLLinphoneSDK/src/main/java/com/hdl/hdllinphonesdk/core/service/HDLLinphoneService.java
@@ -1,6 +1,9 @@
package com.hdl.hdllinphonesdk.core.service;
import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
@@ -11,14 +14,14 @@
import android.os.Handler;
import android.os.IBinder;
import android.os.SystemClock;
import android.support.v4.app.NotificationCompat;
import com.hdl.hdllinphonesdk.HDLLinphoneKit;
import com.hdl.hdllinphonesdk.R;
import com.hdl.hdllinphonesdk.core.callback.PhoneCallback;
import com.hdl.hdllinphonesdk.core.callback.RegistrationCallback;
import com.hdl.hdllinphonesdk.core.linphone.KeepAliveHandler;
import com.hdl.hdllinphonesdk.core.linphone.LinphoneUtils;
import com.hdl.hdllinphonesdk.utils.HDLLog;
import org.linphone.core.Call;
import org.linphone.core.Core;
@@ -51,7 +54,7 @@
    private PendingIntent mKeepAlivePendingIntent;
    private static PhoneCallback sPhoneCallback;//通话状态回调
    private static RegistrationCallback sRegistrationCallback;//账号注册登录状态回调
    private String mRingSoundFile,mPauseSoundFile = null;
    private String mRingSoundFile, mPauseSoundFile = null;
    private Handler mHandler;
    private Timer mTimer;
@@ -73,6 +76,9 @@
    }
    public static Core getCore() {
        if(sInstance == null){
            return null;
        }
        return sInstance.mCore;
    }
@@ -82,26 +88,35 @@
        return null;
    }
    /**
     * 添加通话状态回调
     * @param phoneCallback
     */
    public static void addPhoneCallback(PhoneCallback phoneCallback) {
        sPhoneCallback = phoneCallback;
    }
    public static void removePhoneCallback() {
        if (sPhoneCallback != null) {
            sPhoneCallback = null;
        }
    }
    /**
     * 添加注册状态回调
     * @param registrationCallback
     */
    public static void addRegistrationCallback(RegistrationCallback registrationCallback) {
        sRegistrationCallback = registrationCallback;
    }
    public static void removeRegistrationCallback() {
        if (sRegistrationCallback != null) {
            sRegistrationCallback = null;
        }
    }
    /**
     * 移除所以Callback
     */
    public void removeAllCallback() {
        removePhoneCallback();
        removeRegistrationCallback();
@@ -110,16 +125,13 @@
    @Override
    public void onCreate() {
        super.onCreate();
        hdlStartForeground();
        initLinphone();
        Intent intent = new Intent(this, KeepAliveHandler.class);
        mKeepAlivePendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        ((AlarmManager) this.getSystemService(Context.ALARM_SERVICE)).setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                SystemClock.elapsedRealtime() + 60000, 60000, mKeepAlivePendingIntent);
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
@@ -162,7 +174,7 @@
    @Override
    public void onDestroy() {
        removeAllCallback();
        logout();
        mCore.removeListener(mCoreListener);
        mTimer.cancel();
        mCore.stop();
@@ -174,6 +186,7 @@
        ((AlarmManager) this.getSystemService(Context.ALARM_SERVICE)).cancel(mKeepAlivePendingIntent);
        hdlStopForeground();
        super.onDestroy();
    }
@@ -189,21 +202,19 @@
     * 初始化Linphone
     */
    private void initLinphone() {
        currentCallState = Call.State.Idle;
        String basePath = getFilesDir().getAbsolutePath();
        Factory.instance().setLogCollectionPath(basePath);
        Factory.instance().enableLogCollection(LogCollectionState.Enabled);
        Factory.instance().setDebugMode(false, getString(R.string.app_name));
        // Dump some useful information about the device we're running on
        Log.i(START_LINPHONE_LOGS);
        dumpDeviceInformation();
        dumpInstalledLinphoneInformation();
//        HDLLog.I(START_LINPHONE_LOGS);
//        dumpDeviceInformation();
//        dumpInstalledLinphoneInformation();
        mHandler = new Handler();
        // This will be our main Core listener, it will change activities depending on events
        initCoreListener();
        copyAssetsFromPackage(basePath);
        // Create the Core and add our listener
        mCore = Factory.instance()
                .createCore(basePath + "/.linphonerc", basePath + "/linphonerc", this);
@@ -212,11 +223,14 @@
        configureCore();
    }
    /**
     * 初始化CoreListener监听
     */
    private void initCoreListener() {
        mCoreListener = new CoreListenerStub() {
            @Override
            public void onCallStateChanged(Core core, Call linphoneCall, Call.State state, String message) {
                Log.e(START_LINPHONE_LOGS, "callState: " + state.toString());
                HDLLog.e(START_LINPHONE_LOGS, "callState: " + state.toString());
                currentCallState = state;
                if (sPhoneCallback != null) {
                    if (state == Call.State.IncomingReceived) {
@@ -237,20 +251,28 @@
            @Override
            public void onRegistrationStateChanged(Core core, ProxyConfig proxyConfig, RegistrationState registrationState, String message) {
                String state = registrationState.toString();
                Log.i(START_LINPHONE_LOGS, "registrationState: " + state);
                if (sRegistrationCallback != null) {
                HDLLog.i(START_LINPHONE_LOGS, "registrationState: " + state);
                    if (state.equals(RegistrationState.None.toString())) {
                if (state.equals(RegistrationState.None.toString())) {
                    if (sRegistrationCallback != null){
                        sRegistrationCallback.registrationNone();
                    } else if (state.equals(RegistrationState.Progress.toString())) {
                    }
                } else if (state.equals(RegistrationState.Progress.toString())) {
                    if (sRegistrationCallback != null){
                        sRegistrationCallback.registrationProgress();
                    } else if (state.equals(RegistrationState.Ok.toString())) {
                    }
                } else if (state.equals(RegistrationState.Ok.toString())) {
                    if (sRegistrationCallback != null) {
                        sRegistrationCallback.registrationOk();
                    } else if (state.equals(RegistrationState.Cleared.toString())) {
                    }
                } else if (state.equals(RegistrationState.Cleared.toString())) {
                    removeProxyConfig(core, proxyConfig);
                    if (sRegistrationCallback != null) {
                        sRegistrationCallback.registrationCleared();
                    } else if (state.equals(RegistrationState.Failed.toString())) {
                    }
                } else if (state.equals(RegistrationState.Failed.toString())) {
                    if (sRegistrationCallback != null) {
                        sRegistrationCallback.registrationFailed();
                    }
                }
@@ -258,6 +280,26 @@
        };
    }
    /**
     * 收到注销成功后移除当前代理
     * @param core
     * @param proxyConfig
     */
    void removeProxyConfig(Core core, ProxyConfig proxyConfig) {
        try {
            HDLLog.i(START_LINPHONE_LOGS, "registrationState: 注销成功移除账号:" + proxyConfig.getIdentityAddress().getUsername());
            //收到注销成功后移除当前代理
            if (core != null) {
                core.removeProxyConfig(proxyConfig);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * mCore启动默认参数配置
     */
    private void configureCore() {
        // We will create a directory for user signed certificates if needed
        String basePath = getFilesDir().getAbsolutePath();
@@ -265,71 +307,76 @@
        File f = new File(userCerts);
        if (!f.exists()) {
            if (!f.mkdir()) {
                Log.e(userCerts + " can't be created.");
                HDLLog.E(userCerts + " can't be created.");
            }
        }
        setUserAgent();
        //1.设置存储用户x509证书的目录的路径
        mCore.setUserCertificatesPath(userCerts);
        //2.设置UserAgent
        setUserAgent();
        //3.设置播放铃声
//        mCore.setNativeRingingEnabled(true);
//
//        mCore.setRemoteRingbackTone(mRingSoundFile);
//        mCore.setTone(ToneID.CallWaiting, mRingSoundFile);
        mCore.setRing(mRingSoundFile);
//        mCore.setRing(mRingSoundFile);
//        mCore.setPlayFile(mPauseSoundFile);
        //4.禁用手机摄像头视频采集
//        mCore.enableVideoCapture(false);//禁用手机摄像头视频采集
        mCore.setNetworkReachable(true);
        //回声消除
//        boolean isEchoCancellation = (boolean) SPUtils.get(mServiceContext, "echo_cancellation", true);
        //回声消除
//        mCore.setNetworkReachable(true);
        //5.回声消除
        mCore.enableEchoCancellation(true);
        mCore.enableEchoLimiter(true);
        //自适应码率控制
//        boolean isAdaptiveRateControl = (boolean) SPUtils.get(mServiceContext, "adaptive_rate_control", true);
        mCore.enableMic(true);//启用麦克风
        //6.自适应码率控制
        mCore.enableAdaptiveRateControl(true);
        //audio 码率设置
        mCore.getConfig().setInt("audio", "codec_bitrate_limit", 36);
        //7.audio 码率设置
//        mCore.getConfig().setInt("audio", "codec_bitrate_limit", 36);
        //8.视频相关设置
        mCore.setVideoPreset("custom");//视频预设为custom
        mCore.setPreferredFramerate(5);//FPS优先设置为5
        VideoDefinition preferredVideoDefinition =
                Factory.instance().createVideoDefinitionFromName("qvga");
        mCore.setPreferredVideoDefinition(preferredVideoDefinition);
        mCore.setUploadBandwidth(1536);
        mCore.setDownloadBandwidth(1536);
        mCore.getConfig().setBool("app", "open_h264_download_enabled", true);
        mCore.setPreferredVideoDefinition(preferredVideoDefinition);//视频尺寸偏好默认qvga
        //9.设置带宽限制,带宽单位为kbits/s, 0表示无限
//        mCore.setUploadBandwidth(1536);
//        mCore.setDownloadBandwidth(1536);
        //10.设置视频的默认策略
        VideoActivationPolicy vap = mCore.getVideoActivationPolicy();
        vap.setAutomaticallyInitiate(true);
        mCore.setVideoActivationPolicy(vap);
        // 设置编码格式
        //11.设置编码格式
        setCodecMime();
    }
    /**
     * 设置编码格式
     */
    private void setCodecMime() {
        //1.启用PCMA PCMU 8000Hz
        PayloadType[] ptList = mCore.getAudioPayloadTypes();
        for (PayloadType pt : ptList) {
            org.linphone.mediastream.Log.d("payloadaudio", pt.getMimeType());
            if (pt.getMimeType().equals("PCMA") && pt.getClockRate() == 8000) {
//           HDLLog.i("payloadaudio", pt.getMimeType());
            if ((pt.getMimeType().equals("PCMA") || pt.getMimeType().equals("PCMU")) && pt.getClockRate() == 8000) {
                pt.enable(true);
            } else {
                pt.enable(false);
            }
        }
        mCore.setAudioPayloadTypes(ptList);
        //2.设置VP8、H264、H265 等启用
        PayloadType[] ptVideoList = mCore.getVideoPayloadTypes();
        for (PayloadType pt : ptVideoList) {
//            HDLLog.i("VideoPayload", pt.getMimeType());
            pt.enable(true);
        }
        mCore.setVideoPayloadTypes(ptVideoList);
    }
    /**
     * 设置是否启用铃声,目前发现设置无效待分析原因
     * @param use
     */
    public void enableDeviceRingtone(boolean use) {
        if (use) {
            mCore.setRing(null);
@@ -338,6 +385,9 @@
        }
    }
    /**
     * 设置UserAgent
     */
    private void setUserAgent() {
        try {
            String versionName = this.getPackageManager().getPackageInfo(this.getPackageName(),
@@ -351,6 +401,9 @@
        }
    }
    /**
     * 打印相关信息
     */
    private void dumpDeviceInformation() {
        StringBuilder sb = new StringBuilder();
        sb.append("DEVICE=").append(Build.DEVICE).append("\n");
@@ -362,9 +415,12 @@
            sb.append(abi).append(", ");
        }
        sb.append("\n");
        Log.i(sb.toString());
        HDLLog.I(sb.toString());
    }
    /**
     * 打印版本号信息
     */
    private void dumpInstalledLinphoneInformation() {
        PackageInfo info = null;
        try {
@@ -374,11 +430,11 @@
        }
        if (info != null) {
            Log.i(
            HDLLog.i(
                    "[Service] Linphone version is ",
                    info.versionName + " (" + info.versionCode + ")");
        } else {
            Log.i("[Service] Linphone version is unknown");
            HDLLog.I("[Service] Linphone version is unknown");
        }
    }
@@ -393,18 +449,10 @@
            // The factory config is used to override any other setting, let's copy it each time
            copyFromPackage(R.raw.linphonerc_factory, "linphonerc");
            mRingSoundFile = basePath + "/oldphone_mono.wav";
            copyIfNotExist(R.raw.oldphone_mono,  basePath + "/oldphone_mono.wav");
            copyIfNotExist(R.raw.ringback, basePath + "/ringback.wav");
            mPauseSoundFile = basePath + "/toy_mono.wav";
            copyIfNotExist( R.raw.toy_mono, basePath + "/toy_mono.wav");
//        LinphoneUtils.copyIfNotExist(mServiceContext, R.raw.ringback, mRingBackSoundFile);
//        LinphoneUtils.copyIfNotExist(mServiceContext, R.raw.toy_mono, mPauseSoundFile);
//        LinphoneUtils.copyIfNotExist(mServiceContext, R.raw.linphonerc_default, mLinphoneConfigFile);
//        LinphoneUtils.copyIfNotExist(mServiceContext, R.raw.linphonerc_factory, new File(mLinphoneFactoryConfigFile).getName());
//        LinphoneUtils.copyIfNotExist(mServiceContext, R.raw.lpconfig, mLPConfigXsd);
//        LinphoneUtils.copyIfNotExist(mServiceContext, R.raw.rootca, mLinphoneRootCaFile);
            copyIfNotExist(R.raw.oldphone_mono, mRingSoundFile);
//            copyIfNotExist(R.raw.ringback, basePath + "/ringback.wav");
//            mPauseSoundFile = basePath + "/toy_mono.wav";
//            copyIfNotExist(R.raw.toy_mono, basePath + "/toy_mono.wav");
        } catch (IOException ioe) {
            Log.e(ioe);
@@ -412,6 +460,12 @@
    }
    /**
     * copyIfNotExist
     * @param ressourceId
     * @param target
     * @throws IOException
     */
    private void copyIfNotExist(int ressourceId, String target) throws IOException {
        File lFileToCopy = new File(target);
        if (!lFileToCopy.exists()) {
@@ -419,6 +473,12 @@
        }
    }
    /**
     * copyFromPackage
     * @param ressourceId
     * @param target
     * @throws IOException
     */
    private void copyFromPackage(int ressourceId, String target) throws IOException {
        FileOutputStream lOutputStream = openFileOutput(target, 0);
        InputStream lInputStream = getResources().openRawResource(ressourceId);
@@ -438,4 +498,44 @@
    public Call.State getCurrentCallState() {
        return currentCallState;
    }
    /**
     * 注销所有账号
     */
    void logout() {
        try {
            if (mCore != null) {
                ProxyConfig[] configs = mCore.getProxyConfigList();
                for (ProxyConfig config : configs) {
                    if (config != null) {
                        config.edit();
                        config.enableRegister(false);
                        config.done();
                    }
                }
                HDLLog.E("注销所有账号");
//                core.clearAllAuthInfo();
//                core.clearProxyConfig();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //通知ID
    public static final int NOTIFICATION_ID = 2;
    /**
     * 解决android8.0以上无法启动服务的问题
     */
    void hdlStartForeground() {
    }
    /**
     * stopForeground
     */
    void hdlStopForeground() {
//        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
//            stopForeground(true);
//        }
    }
}