소스 검색

集成sip通话功能

weizhengliang 3 년 전
부모
커밋
dc866de479

+ 10 - 0
build.gradle

@@ -108,6 +108,11 @@ buildscript {
         google()
 
         maven { url "https://jitpack.io" }
+
+        maven {
+            // Replace snapshots by releases for releases !
+            url "https://linphone.org/maven_repository"
+        }
     }
 }
 /**
@@ -124,6 +129,11 @@ allprojects {
         google()
 
         maven { url "https://jitpack.io" }
+
+        maven {
+            // Replace snapshots by releases for releases !
+            url "https://linphone.org/maven_repository"
+        }
     }
     tasks.withType(Javadoc) { // 新增
         options.addStringOption('Xdoclint:none', '-quiet')

+ 4 - 1
callingbed/build.gradle

@@ -82,9 +82,12 @@ dependencies {
      */
     compile project(':welcome')
     compile project(':middleware')
-    compile project(':sip2')
+    //compile project(':sip2')
     //compile project(':bedlib')
 
+    //linphone sip
+    implementation "org.linphone:linphone-sdk-android:4.3.3"
+
     //web rtc
     //compile project(':webrtc')
     //compile project(':libwebrtc')

+ 4 - 0
callingbed/src/main/AndroidManifest.xml

@@ -23,5 +23,9 @@
         <activity android:name=".activity.AppUpdateActivity"
             android:screenOrientation="landscape"
             android:launchMode="singleTask"/>
+
+        <service
+            android:name=".sip.WdklSipService"
+            android:label="@string/app_name" />
     </application>
 </manifest>

+ 82 - 18
callingbed/src/main/java/com/wdkl/app/ncs/callingbed/activity/CallingbedActivity.kt

@@ -1,11 +1,19 @@
 package com.wdkl.app.ncs.callingbed.activity
 
+//import com.wdkl.app.ncs.callingbed.sip.SipHelper
+//import com.wdkl.app.ncs.callingbed.sip.SipStatus
+//import com.vvsip.ansip.IVvsipServiceListener
+//import com.vvsip.ansip.VvsipCall
+//import com.wdkl.app.ncs.callingbed.fragment.SkyCallFragment
 import android.content.BroadcastReceiver
 import android.content.Context
 import android.content.Intent
 import android.content.IntentFilter
 import android.net.ConnectivityManager
-import android.os.*
+import android.os.Build
+import android.os.Bundle
+import android.os.Handler
+import android.os.Message
 import android.support.v4.app.Fragment
 import android.support.v7.widget.LinearLayoutManager
 import android.text.TextUtils
@@ -16,20 +24,18 @@ import com.enation.javashop.android.jrouter.external.annotation.Router
 import com.enation.javashop.net.engine.model.NetState
 import com.google.gson.Gson
 import com.wdkl.app.ncs.callingbed.BuildConfig
-//import com.wdkl.app.ncs.callingbed.sip.SipHelper
-//import com.wdkl.app.ncs.callingbed.sip.SipStatus
-//import com.vvsip.ansip.IVvsipServiceListener
-//import com.vvsip.ansip.VvsipCall
 import com.wdkl.app.ncs.callingbed.R
 import com.wdkl.app.ncs.callingbed.adapter.NurseConfigAdpter
+import com.wdkl.app.ncs.callingbed.agreement.CallingbedAgreement
 import com.wdkl.app.ncs.callingbed.databinding.CallingbedMainLayBinding
-import com.wdkl.app.ncs.callingbed.fragment.*
+import com.wdkl.app.ncs.callingbed.fragment.CostFragment
+import com.wdkl.app.ncs.callingbed.fragment.MainFragment
+import com.wdkl.app.ncs.callingbed.fragment.QrCodeFragment
+import com.wdkl.app.ncs.callingbed.fragment.SipCallFragment
 import com.wdkl.app.ncs.callingbed.helper.*
 import com.wdkl.app.ncs.callingbed.launch.CallingbedLaunch
 import com.wdkl.app.ncs.callingbed.settings.SettingConfig
-import com.wdkl.app.ncs.callingbed.agreement.CallingbedAgreement
-//import com.wdkl.app.ncs.callingbed.fragment.SkyCallFragment
-import com.wdkl.app.ncs.callingbed.helper.ScreenManagerUtil
+import com.wdkl.app.ncs.callingbed.sip.WdklSipService
 import com.wdkl.ncs.android.lib.base.BaseActivity
 import com.wdkl.ncs.android.lib.base.BaseApplication
 import com.wdkl.ncs.android.lib.utils.AppTool
@@ -37,7 +43,6 @@ import com.wdkl.ncs.android.lib.utils.TimeHandle
 import com.wdkl.ncs.android.lib.utils.push
 import com.wdkl.ncs.android.lib.utils.showMessage
 import com.wdkl.ncs.android.lib.vo.filter
-import com.wdkl.ncs.android.lib.widget.MenuDialog
 import com.wdkl.ncs.android.middleware.common.Constant
 import com.wdkl.ncs.android.middleware.common.MessageEvent
 import com.wdkl.ncs.android.middleware.common.SipStatus
@@ -49,11 +54,9 @@ import com.wdkl.ncs.android.middleware.model.dos.PartSettingDO
 import com.wdkl.ncs.android.middleware.model.dto.NurseConfigDto
 import com.wdkl.ncs.android.middleware.model.dto.TcpSeverDTO
 import com.wdkl.ncs.android.middleware.model.vo.BedDeviceInfoVO
-import com.wdkl.ncs.android.middleware.model.vo.CustomerInfoVO
 import com.wdkl.ncs.android.middleware.model.vo.InteractionVO
 import com.wdkl.ncs.android.middleware.tcp.TcpClient
 import com.wdkl.ncs.android.middleware.tcp.channel.OtherUtil
-import com.wdkl.ncs.android.middleware.tcp.channel.VideoUtil
 import com.wdkl.ncs.android.middleware.tcp.channel.VoiceUtil
 import com.wdkl.ncs.android.middleware.tcp.dto.TcpModel
 import com.wdkl.ncs.android.middleware.tcp.enums.TcpAction
@@ -63,11 +66,13 @@ import kotlinx.android.synthetic.main.view_title_layout.*
 import org.greenrobot.eventbus.EventBus
 import org.greenrobot.eventbus.Subscribe
 import org.greenrobot.eventbus.ThreadMode
+import org.linphone.core.AccountCreator
+import org.linphone.core.RegistrationState
+import org.linphone.core.TransportType
 import serialporttest.utils.SerialPortUtil
 import java.io.DataOutputStream
 import java.io.IOException
 import java.io.PrintWriter
-import java.lang.Process
 import java.lang.ref.WeakReference
 
 
@@ -102,6 +107,7 @@ class CallingbedActivity :BaseActivity<CallingbedActivityPresenter, CallingbedMa
 
     //通话界面fragment
     private var skyCallFragment: Fragment? = null
+    private var mAccountCreator: AccountCreator? = null
 
     //网络异常计数
     private var netErrCount : Int = 0
@@ -123,7 +129,7 @@ class CallingbedActivity :BaseActivity<CallingbedActivityPresenter, CallingbedMa
     //呼叫护士
     //private val callNurseFragment = "call_nurse_fragment"
 
-    private val uninstallApk = false
+    private val uninstallApk = true
 
     companion object {
         private const val TIME_WHAT = 1000
@@ -141,6 +147,9 @@ class CallingbedActivity :BaseActivity<CallingbedActivityPresenter, CallingbedMa
         //开始ping网络,30秒ping一次
         //NetHelper.startNetCheck()
 
+        //启动sip服务
+        startService(Intent().setClass(this, WdklSipService::class.java))
+
         //获取mac地址
         Constant.LOCAL_MAC = NetHelper.getInstance().macAddress
 
@@ -213,7 +222,7 @@ class CallingbedActivity :BaseActivity<CallingbedActivityPresenter, CallingbedMa
 
 
     private fun RunAsRoot(cmds: ArrayList<String>) {
-        val p = Runtime.getRuntime().exec("su")
+        val p = Runtime.getRuntime().exec("sh")
         val os = DataOutputStream(p.outputStream)
         for (tmpCmd in cmds) {
             os.writeBytes(
@@ -400,6 +409,21 @@ class CallingbedActivity :BaseActivity<CallingbedActivityPresenter, CallingbedMa
 
         presenter.loadPartSettings(Constant.PART_ID)
 
+        //配置sip账户
+        if (WdklSipService.getCore() != null) {
+            mAccountCreator = WdklSipService.getCore().createAccountCreator(null)
+            // 以下三项必须
+            mAccountCreator!!.setDomain(Constant.TCP_SERVER_URL)
+            mAccountCreator!!.setUsername("3309")
+            mAccountCreator!!.setPassword("3309")
+            //默认使用udp
+            mAccountCreator!!.transport = TransportType.Udp
+
+            // 这里会自动创建代理配置、认证信息到 SIP核心
+            val cfg = mAccountCreator!!.createProxyConfig()
+            // 确保新创建的是最新
+            WdklSipService.getCore().defaultProxyConfig = cfg
+        }
     }
 
     override fun setPartSettings(partSetting: PartSettingDO) {
@@ -916,10 +940,16 @@ class CallingbedActivity :BaseActivity<CallingbedActivityPresenter, CallingbedMa
 
             //Sip注册状态
             Constant.EVENT_SIP_REGISTER_STATUS -> {
-                if (messageEvent.message is String) run {
+                /*if (messageEvent.message is String) run {
                     val status = messageEvent.message as String
                     Log.d("sip", "sip regist status: " + status)
                     updateStatus(status)
+                }*/
+
+                if (messageEvent.message is RegistrationState) {
+                    val state = messageEvent.message as RegistrationState
+                    Log.d("callingbed", "sip register state: $state")
+                    updateSipState(state)
                 }
             }
 
@@ -1060,6 +1090,32 @@ class CallingbedActivity :BaseActivity<CallingbedActivityPresenter, CallingbedMa
         }
     }
 
+    private fun updateSipState(state: RegistrationState) {
+        runOnUiThread {
+            when (state) {
+                RegistrationState.Ok -> {
+                    //连接完成
+                    view_title_layout_tv_point.setBackgroundResource(R.color.green)
+                }
+
+                RegistrationState.Failed -> {
+                    //连接错误
+                    view_title_layout_tv_point.setBackgroundResource(R.color.red_color)
+                }
+
+                RegistrationState.Progress -> {
+                    //正在连接
+                    view_title_layout_tv_point.setBackgroundResource(R.color.yellow_color)
+                }
+
+                RegistrationState.None, RegistrationState.Cleared -> {
+                    //默认状态,断开连接
+                    view_title_layout_tv_point.setBackgroundResource(R.color.register_text_color)
+                }
+            }
+        }
+    }
+
     private fun updateNetState() {
         if (NetHelper.getInstance().networkType == ConnectivityManager.TYPE_WIFI) {
             view_title_layout_iv_wifi.visibility = View.VISIBLE
@@ -1112,16 +1168,24 @@ class CallingbedActivity :BaseActivity<CallingbedActivityPresenter, CallingbedMa
     private fun updateTcpState() {
         if (Constant.TCP_CONNECTED) {
             view_title_layout_iv_tcp.setImageResource(R.mipmap.ic_tcp_success)
-            view_title_layout_tv_point.setBackgroundResource(R.color.green)
+            //view_title_layout_tv_point.setBackgroundResource(R.color.green)
         } else {
             view_title_layout_iv_tcp.setImageResource(R.mipmap.ic_tcp_fail)
-            view_title_layout_tv_point.setBackgroundResource(R.color.red_color)
+            //view_title_layout_tv_point.setBackgroundResource(R.color.red_color)
         }
     }
 
     inner class TimeReceiver: BroadcastReceiver() {
         override fun onReceive(context: Context, intent: Intent) {
             if (intent.action == Intent.ACTION_TIME_TICK) {
+                //更新sip注册状态
+                if (WdklSipService.getCore() != null) {
+                    val proxyConfig = WdklSipService.getCore().defaultProxyConfig
+                    if (proxyConfig != null) {
+                        updateSipState(proxyConfig.state)
+                    }
+                }
+
                 updateNetState()
                 if (initialized) {
                     updateSettings(false)

+ 57 - 66
callingbed/src/main/java/com/wdkl/app/ncs/callingbed/fragment/SipCallFragment.kt

@@ -9,6 +9,7 @@ import android.view.View
 import com.google.gson.Gson
 import com.wdkl.app.ncs.callingbed.R
 import com.wdkl.app.ncs.callingbed.helper.RingPlayHelper
+import com.wdkl.app.ncs.callingbed.sip.WdklSipService
 import com.wdkl.ncs.android.lib.utils.AppTool
 import com.wdkl.ncs.android.lib.utils.showMessage
 import com.wdkl.ncs.android.middleware.common.Constant
@@ -21,6 +22,9 @@ import com.wdkl.ncs.android.middleware.tcp.enums.TcpType
 import kotlinx.android.synthetic.main.sip_voice_call_layout.*
 import org.greenrobot.eventbus.Subscribe
 import org.greenrobot.eventbus.ThreadMode
+import org.linphone.core.Call
+import org.linphone.core.Core
+import org.linphone.core.CoreListenerStub
 
 class SipCallFragment: BaseCallFragment() {
     private val TAG = "SipCallFragment"
@@ -29,6 +33,7 @@ class SipCallFragment: BaseCallFragment() {
     var fromId: Int = -1
 
     private var interactionVO: InteractionVO? = null
+    private var sipCore: Core? = null
 
     private val handler = Handler(Looper.getMainLooper())
 
@@ -38,6 +43,33 @@ class SipCallFragment: BaseCallFragment() {
 
     private var callSuccess: Boolean = false
 
+
+    // 配置通话状态监听
+    private val coreListener = object : CoreListenerStub() {
+        override fun onCallStateChanged(
+            core: Core,
+            call: Call,
+            state: Call.State,
+            message: String
+        ) {
+            if (state == Call.State.IncomingReceived) {
+                //来电时将自动接听
+                if (sipCore != null) {
+                    val params = sipCore!!.createCallParams(call)
+                    params.enableVideo(false)
+                    call.acceptWithParams(params)
+                } else {
+                    VoiceUtil.handoffAudioCall(Constant.DEVICE_ID, fromId, Constant.interactionId)
+                    callEnd()
+                }
+            } else if (state == Call.State.End || state == Call.State.Released) {
+                callEnd()
+            } else if (state == Call.State.Connected) {
+                showCalling()
+            }
+        }
+    }
+
     override fun getLayId(): Int {
         return R.layout.sip_voice_call_layout
     }
@@ -51,6 +83,11 @@ class SipCallFragment: BaseCallFragment() {
             interactionVO = Gson().fromJson(tcpModel!!.data.toString(), InteractionVO::class.java)
         }
 
+        sipCore = WdklSipService.getCore()
+        if (sipCore != null) {
+            sipCore!!.addListener(coreListener)
+        }
+
         when (callState) {
             0 -> {
                 //去电
@@ -81,6 +118,7 @@ class SipCallFragment: BaseCallFragment() {
                 }
 
                 VoiceUtil.handoffAudioCall(Constant.DEVICE_ID, fromId, interactionVO?.id)
+                callTerminate()
                 callEnd()
             } else {
                 Constant.CALL_STATE = Constant.CALL_STANDBY
@@ -112,6 +150,9 @@ class SipCallFragment: BaseCallFragment() {
         if (sip_voice_call_timer != null) {
             sip_voice_call_timer.stop()
         }
+        if (sipCore != null) {
+            sipCore!!.removeListener(coreListener)
+        }
         RingPlayHelper.stopRingTone()
     }
 
@@ -206,74 +247,16 @@ class SipCallFragment: BaseCallFragment() {
         }
     }
 
-
-    /********************************************************
-     ********************* 通话回调 ********************
-     * 注意: 如涉及到UI更新的需要在主线程处理,务必注意
-     ********************************************************/
-    /*override fun didChangeState(var1: EnumType.CallState?) {
-        if (var1 == EnumType.CallState.Connected) {
-            handler.post {
-                RingPlayHelper.stopRingTone()
-                //更新界面显示
-                showCalling()
+    private fun callTerminate() {
+        if (sipCore != null && sipCore!!.callsNb > 0) {
+            var call = sipCore!!.currentCall
+            if (call == null) {
+                call = sipCore!!.calls[0]
             }
+            call!!.terminate()
         }
     }
 
-    override fun didDisconnected(userId: String?) {
-        Log.i(TAG, "disconnected user:" + userId + ",call user:" + Constant.TARGET_SIP)
-        if (userId.equals(Constant.TARGET_SIP)) {
-            Log.w(TAG, "didDisconnected: $userId")
-            handler.post {
-                showMessage("$userId 失去连接")
-                callEnd()
-            }
-        }
-    }
-
-    override fun didCreateLocalVideoTrack() {
-
-    }
-
-    override fun didError(error: String?) {
-        Log.e(TAG, "didError: $error")
-        handler.post {
-            showMessage("通话错误")
-            callEnd()
-        }
-    }
-
-    override fun didHangUp(handlerId: BigInteger) {
-        Log.e("hangup", "socket hangup")
-        handler.post {
-            callEnd()
-        }
-    }
-
-    override fun didReceiveRemoteVideoTrack(userId: BigInteger?) {
-        // TODO("Not yet implemented")
-    }
-
-
-    override fun didCallEndWithReason(var1: EnumType.CallEndReason?) {
-        handler.post {
-            callEnd()
-        }
-    }
-
-    override fun didChangeMode(isAudioOnly: Boolean) {
-
-    }
-
-    override fun didUserLeave(userId: BigInteger?) {
-        Log.w(TAG, "didUserLeave:"+userId)
-        handler.post {
-            callEnd()
-        }
-    }*/
-
-
 
     @Subscribe(threadMode = ThreadMode.MAIN)
     fun onMoonEvent(messageEvent: MessageEvent) {
@@ -297,12 +280,19 @@ class SipCallFragment: BaseCallFragment() {
                                 Constant.interactionId = curInteractionVO.id
                                 fromId = curTcpModel.fromId
                                 acceptCall()
-                                if (TextUtils.isEmpty(curInteractionVO.toSipId)) {
+                                if (sipCore == null && TextUtils.isEmpty(curInteractionVO.toSipId)) {
                                     //通话失败,重置并返回主界面
-                                    showMessage("targetSipId为空!")
+                                    showMessage("Core或targetSipId为空!")
                                     Constant.CALL_STATE = Constant.CALL_STANDBY
                                     VoiceUtil.handoffAudioCall(Constant.DEVICE_ID, fromId, Constant.interactionId)
                                     callEnd()
+                                } else {
+                                    val addressToCall = sipCore!!.interpretUrl("3305")
+                                    val params = sipCore!!.createCallParams(null)
+                                    params.enableVideo(false)
+                                    if (addressToCall != null) {
+                                        sipCore!!.inviteAddressWithParams(addressToCall, params)
+                                    }
                                 }
                             } else if (curTcpModel.getAction() == TcpAction.VoiceAction.REJECT) {
                                 //我方呼出,对方拒绝
@@ -365,6 +355,7 @@ class SipCallFragment: BaseCallFragment() {
                     } else if (serialAction.equals("handoff")) {
                         Constant.CALL_STATE = Constant.CALL_STANDBY
                         VoiceUtil.handoffAudioCall(Constant.DEVICE_ID, fromId, Constant.interactionId)
+                        callTerminate()
                         callEnd()
                     } else if (serialAction.equals("reject")) {
                         RingPlayHelper.stopRingTone()

+ 231 - 0
callingbed/src/main/java/com/wdkl/app/ncs/callingbed/sip/WdklSipService.java

@@ -0,0 +1,231 @@
+package com.wdkl.app.ncs.callingbed.sip;
+
+import android.app.Service;
+import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.os.Handler;
+import android.os.IBinder;
+import android.support.annotation.Nullable;
+import android.widget.Toast;
+
+import com.wdkl.app.ncs.callingbed.R;
+import com.wdkl.ncs.android.middleware.common.Constant;
+import com.wdkl.ncs.android.middleware.common.MessageEvent;
+
+import org.greenrobot.eventbus.EventBus;
+import org.linphone.core.Call;
+import org.linphone.core.CallParams;
+import org.linphone.core.Core;
+import org.linphone.core.CoreListenerStub;
+import org.linphone.core.Factory;
+import org.linphone.core.LogCollectionState;
+import org.linphone.core.ProxyConfig;
+import org.linphone.core.RegistrationState;
+import org.linphone.core.tools.Log;
+import org.linphone.mediastream.Version;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Timer;
+import java.util.TimerTask;
+
+public class WdklSipService extends Service {
+    private static final String START_SIPPHONE_LOGS = " ==== Device information dump ====";
+    //单例化服务,以便全局调用
+    private static WdklSipService sInstance;
+
+    private Handler mHandler;
+    private Timer mTimer;
+
+    private Core mCore;
+    private CoreListenerStub mCoreListener;
+
+    public static boolean isReady() {
+        return sInstance != null;
+    }
+
+    public static WdklSipService getInstance() {
+        return sInstance;
+    }
+
+    public static Core getCore() {
+        return sInstance.mCore;
+    }
+
+    @Nullable
+    @Override
+    public IBinder onBind(Intent intent) {
+        return null;
+    }
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+
+        Toast.makeText(WdklSipService.this, "wdkl sip service", Toast.LENGTH_SHORT).show();
+
+        //首次调用必须使用 Factory相关方法
+        //这里开户调试日志及设置路径
+        String basePath = getFilesDir().getAbsolutePath();
+        Factory.instance().setLogCollectionPath(basePath);
+        Factory.instance().enableLogCollection(LogCollectionState.Enabled);
+        Factory.instance().setDebugMode(true, getString(R.string.app_name));
+
+        //收集一些设备信息
+        Log.i(START_SIPPHONE_LOGS);
+        dumpDeviceInformation();
+        dumpInstalledLinphoneInformation();
+
+        mHandler = new Handler();
+        //主监听器,根据事件调用界面
+        mCoreListener = new CoreListenerStub() {
+            @Override
+            public void onRegistrationStateChanged(Core core, ProxyConfig cfg, RegistrationState state, String message) {
+                EventBus.getDefault().post(new MessageEvent(state, Constant.EVENT_SIP_REGISTER_STATUS));
+            }
+        };
+
+        try {
+            //复制一些源资源
+            //默认配置只能在首次时安装一次
+            copyIfNotExist(R.raw.linphonerc_default, basePath + "/.wdkl_sip_rc");
+            //用户配置,每次复制
+            copyFromPackage(R.raw.linphonerc_factory, "wdkl_sip_rc");
+        } catch (IOException ioe) {
+            Log.e(ioe);
+        }
+
+        //创建SIP核心并加载监听器
+        mCore = Factory.instance()
+                .createCore(basePath + "/.wdkl_sip_rc", basePath + "/wdkl_sip_rc", this);
+        mCore.addListener(mCoreListener);
+        //SIP核心配置完成
+        configureCore();
+    }
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        super.onStartCommand(intent, flags, startId);
+        Toast.makeText(WdklSipService.this, "sip服务已启动", Toast.LENGTH_SHORT).show();
+
+        //如果服务已经在运行,则返回
+        if (sInstance != null) {
+            return START_STICKY;
+        }
+
+        //一旦服务启动,则一直保持
+        sInstance = this;
+
+        //SIP核心在创建和配置完成后,开启
+        mCore.start();
+        //必须定时运行 SIP核心 iterate()
+        TimerTask lTask = new TimerTask() {
+            @Override
+            public void run() {
+                mHandler.post(
+                        new Runnable() {
+                            @Override
+                            public void run() {
+                                if (mCore != null) {
+                                    mCore.iterate();
+                                }
+                            }
+                        });
+            }
+        };
+        mTimer = new Timer("wdkl sip scheduler");
+        mTimer.schedule(lTask, 0, 20);
+
+        return START_STICKY;
+    }
+
+    @Override
+    public void onDestroy() {
+        mCore.removeListener(mCoreListener);
+        mTimer.cancel();
+        mCore.stop();
+        // A stopped Core can be started again
+        // To ensure resources are freed, we must ensure it will be garbage collected
+        mCore = null;
+        // Don't forget to free the singleton as well
+        sInstance = null;
+
+        super.onDestroy();
+    }
+
+    @Override
+    public void onTaskRemoved(Intent rootIntent) {
+        // For this sample we will kill the Service at the same time we kill the app
+        stopSelf();
+
+        super.onTaskRemoved(rootIntent);
+    }
+
+    private void configureCore() {
+        // We will create a directory for user signed certificates if needed
+        String basePath = getFilesDir().getAbsolutePath();
+        String userCerts = basePath + "/user-certs";
+        File f = new File(userCerts);
+        if (!f.exists()) {
+            if (!f.mkdir()) {
+                Log.e(userCerts + " can't be created.");
+            }
+        }
+        mCore.setUserCertificatesPath(userCerts);
+    }
+
+    private void dumpDeviceInformation() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("DEVICE=").append(Build.DEVICE).append("\n");
+        sb.append("MODEL=").append(Build.MODEL).append("\n");
+        sb.append("MANUFACTURER=").append(Build.MANUFACTURER).append("\n");
+        sb.append("SDK=").append(Build.VERSION.SDK_INT).append("\n");
+        sb.append("Supported ABIs=");
+        for (String abi : Version.getCpuAbis()) {
+            sb.append(abi).append(", ");
+        }
+        sb.append("\n");
+        Log.i(sb.toString());
+    }
+
+    private void dumpInstalledLinphoneInformation() {
+        PackageInfo info = null;
+        try {
+            info = getPackageManager().getPackageInfo(getPackageName(), 0);
+        } catch (PackageManager.NameNotFoundException nnfe) {
+            Log.e(nnfe);
+        }
+
+        if (info != null) {
+            Log.i(
+                    "[Service] sipphone version is ",
+                    info.versionName + " (" + info.versionCode + ")");
+        } else {
+            Log.i("[Service] sipphone version is unknown");
+        }
+    }
+
+    private void copyIfNotExist(int ressourceId, String target) throws IOException {
+        File lFileToCopy = new File(target);
+        if (!lFileToCopy.exists()) {
+            copyFromPackage(ressourceId, lFileToCopy.getName());
+        }
+    }
+
+    private void copyFromPackage(int ressourceId, String target) throws IOException {
+        FileOutputStream lOutputStream = openFileOutput(target, 0);
+        InputStream lInputStream = getResources().openRawResource(ressourceId);
+        int readByte;
+        byte[] buff = new byte[8048];
+        while ((readByte = lInputStream.read(buff)) != -1) {
+            lOutputStream.write(buff, 0, readByte);
+        }
+        lOutputStream.flush();
+        lOutputStream.close();
+        lInputStream.close();
+    }
+}

+ 1 - 1
callingbed/src/main/res/layout/view_title_layout.xml

@@ -12,7 +12,7 @@
         android:layout_height="12dp"
         android:layout_centerVertical="true"
         android:layout_marginLeft="20dp"
-        android:background="@color/red_color"/>
+        android:background="@color/register_text_color"/>
 
     <!--医院名称-->
     <TextView

+ 20 - 0
callingbed/src/main/res/raw/linphonerc_default

@@ -0,0 +1,20 @@
+[sip]
+contact="Linphone Android" <sip:allen@8.129.220.143>
+use_info=0
+use_ipv6=1
+keepalive_period=30000
+sip_port=-1
+sip_tcp_port=-1
+sip_tls_port=-1
+media_encryption=none
+
+[video]
+size=vga
+
+[app]
+tunnel=disabled
+push_notification=1
+
+[misc]
+max_calls=10
+history_max_size=100

+ 34 - 0
callingbed/src/main/res/raw/linphonerc_factory

@@ -0,0 +1,34 @@
+
+#
+#This file shall not contain path referencing package name, in order to be portable when app is renamed.
+#Paths to resources must be set from LinphoneManager, after creating LinphoneCore.
+[net]
+mtu=1300
+#Because dynamic bitrate adaption can increase bitrate, we must allow "no limit"
+download_bw=0
+upload_bw=0
+force_ice_disablement=0
+
+[sip]
+guess_hostname=1
+register_only_when_network_is_up=1
+auto_net_state_mon=1
+auto_answer_replacing_calls=1
+ping_with_options=0
+use_cpim=1
+
+[video]
+displaytype=MSAndroidTextureDisplay
+
+[misc]
+enable_basic_to_client_group_chat_room_migration=0
+enable_simple_group_chat_message_state=0
+aggregate_imdn=1
+notify_each_friend_individually_when_presence_received=0
+
+[app]
+activation_code_length=4
+prefer_basic_chat_room=1
+
+[assistant]
+xmlrpc_url=https://subscribe.linphone.org:444/wizard.php

+ 2 - 2
settings.gradle

@@ -1,4 +1,4 @@
-include ':app', ':common', ':welcome', ':home', ':resource', ':middleware', ':extra', ':callingbed', ':bedlib', 'sip2'
+include ':app', ':common', ':welcome', ':home', ':resource', ':middleware', ':extra', ':callingbed', ':bedlib'
 
 //'webrtc', 'rtc-chat', 'libwebrtc'
-//':janus'
+//':janus', 'sip2'