【问题标题】:How to integrate SIP into Android?如何将 SIP 集成到 Android 中?
【发布时间】:2012-09-20 01:34:16
【问题描述】:

如何在Android中实现SIP协议? 是否有任何 SDK 或库可以轻松地将其实现到 Android 中?

【问题讨论】:

    标签: android sip voip rtp sdp


    【解决方案1】:

    Here 是带有示例代码的第三方库。你可以用这个,我用过,效果很好。

    【讨论】:

    • 我需要说明为什么要使用这个库??正如@Priyank 提到的,Android 2.3 支持 SIP 的 API,并且 sip 堆栈可用使用这个库有什么好处???
    【解决方案2】:

    Android 2.3 或更高版本为 SIP 提供 API。

    请参考此链接SIP in Android

    您也可以从Sample 看到 SIP 的 DEMO 项目

    更新:
    github 上的 Android SDK 示例。
    SipDemo1, SipDemo2

    【讨论】:

    • 部分运营商禁用了Android原生SIP,部分平板不支持。此外,较旧的 Android 版本不支持 SIP。
    • @HankKarl 正如你所说,某些运营商禁用了本地 SIP 支持,我可以使用我的 WIFI 获得它吗????
    【解决方案3】:

    在android 4.0.3 SDK版本(API级别-15)的示例中搜索SipDemo项目

    【讨论】:

    • 但是这个 SIPDemo 有严重的问题,我无法注册我的 SIP 配置文件,它总是显示注册失败错误你知道如何解决它
    【解决方案4】:

    我对这类问题调查了很长时间,发现SipManagerSipProfile 很不幸,而且非常糟糕。

    所以我找到了一个 Linphone 库。他们的 wiki 有一个 link。我使用 maven 在我的项目中实现了它:

    repositories {
        ...
        maven { "https://linphone.org/maven_repository/"}
    }
    

    还有一个在 gitlab 上使用它的示例:link here,现在还挺新鲜的 :)

    如果链接崩溃,我只需复制/粘贴如何使用 linphone 的核心的最重要部分:

    public class LinphoneService extends Service {
        private static final String START_LINPHONE_LOGS = " ==== Device information dump ====";
        // Keep a static reference to the Service so we can access it from anywhere in the app
        private static LinphoneService sInstance;
    
        private Handler mHandler;
        private Timer mTimer;
    
        private Core mCore;
        private CoreListenerStub mCoreListener;
    
        public static boolean isReady() {
            return sInstance != null;
        }
    
        public static LinphoneService 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();
    
            // The first call to liblinphone SDK MUST BE to a Factory method
            // So let's enable the library debug logs & log collection
            String basePath = getFilesDir().getAbsolutePath();
            Factory.instance().setLogCollectionPath(basePath);
            Factory.instance().enableLogCollection(LogCollectionState.Enabled);
            Factory.instance().setDebugMode(true, getString(R.string.app_name));
    
            // Dump some useful information about the device we're running on
            Log.i(START_LINPHONE_LOGS);
            dumpDeviceInformation();
            dumpInstalledLinphoneInformation();
    
            mHandler = new Handler();
            // This will be our main Core listener, it will change activities depending on events
            mCoreListener = new CoreListenerStub() {
                @Override
                public void onCallStateChanged(Core core, Call call, Call.State state, String message) {
                    Toast.makeText(LinphoneService.this, message, Toast.LENGTH_SHORT).show();
    
                    if (state == Call.State.IncomingReceived) {
                        Toast.makeText(LinphoneService.this, "Incoming call received, answering it automatically", Toast.LENGTH_LONG).show();
                        // For this sample we will automatically answer incoming calls
                        CallParams params = getCore().createCallParams(call);
                        params.enableVideo(true);
                        call.acceptWithParams(params);
                    } else if (state == Call.State.Connected) {
                        // This stats means the call has been established, let's start the call activity
                        Intent intent = new Intent(LinphoneService.this, CallActivity.class);
                        // As it is the Service that is starting the activity, we have to give this flag
                        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        startActivity(intent);
                    }
                }
            };
    
            try {
                // Let's copy some RAW resources to the device
                // The default config file must only be installed once (the first time)
                copyIfNotExist(R.raw.linphonerc_default, basePath + "/.linphonerc");
                // The factory config is used to override any other setting, let's copy it each time
                copyFromPackage(R.raw.linphonerc_factory, "linphonerc");
            } catch (IOException ioe) {
                Log.e(ioe);
            }
    
            // Create the Core and add our listener
            mCore = Factory.instance()
                    .createCore(basePath + "/.linphonerc", basePath + "/linphonerc", this);
            mCore.addListener(mCoreListener);
            // Core is ready to be configured
            configureCore();
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            super.onStartCommand(intent, flags, startId);
    
            // If our Service is already running, no need to continue
            if (sInstance != null) {
                return START_STICKY;
            }
    
            // Our Service has been started, we can keep our reference on it
            // From now one the Launcher will be able to call onServiceReady()
            sInstance = this;
    
            // Core must be started after being created and configured
            mCore.start();
            // We also MUST call the iterate() method of the Core on a regular basis
            TimerTask lTask =
                    new TimerTask() {
                        @Override
                        public void run() {
                            mHandler.post(
                                    new Runnable() {
                                        @Override
                                        public void run() {
                                            if (mCore != null) {
                                                mCore.iterate();
                                            }
                                        }
                                    });
                        }
                    };
            mTimer = new Timer("Linphone 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] Linphone version is ",
                        info.versionName + " (" + info.versionCode + ")");
            } else {
                Log.i("[Service] Linphone 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();
        }
    }
    

    我希望这会对某人有所帮助,因为我花了很多时间试图找到它!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-18
      相关资源
      最近更新 更多