Cody Blog

Software development

使用 linphone 函式庫發生 exc_bad_access 的除錯經驗

exc_bad_access

在叫用 linphone 的函式庫時,發生 exc_bad_access的錯誤,因為這個錯誤往往發生的地方跟掛掉的地方是不一樣的,所以比較難除錯。

EXC_BAD_ACCESS

是因為對已經釋放的記憶體進行了非法操作,程式會直接 Crash,無法用 error handle catch 來處理。

exc_bad_access

Crash 片段

zombie

記錄發生 crash 的地方不只有一處,共同的特色就是都是掛在 linphone 的函式庫:

發生位置1 linphone_core_iterate():

@objc func iterate(){
    let lc = LinphoneManager.getLc()
    if  lc != nil{
        linphone_core_iterate(lc); /* first iterate initiates registration */
    }
}

發生位置2 linphone_core_iterate():

if let phone = phoneNumber, lc = LinphoneManager.lc {
    nameLabel.text = calleeName!
    linphone_core_invite(lc, phone)
}

透 Debug build 測試

因為預設從 linphone 網站下載的 iphone sdk 是沒有 debug symbol 的,所以在發生 crash 的時侯,只能看到看組合語言: acc EXC_I386_GPFLT

雖然有 linphone 的函式名稱,但是對於問題的幫助不。所以我就直接 build 一個 有 debug symbol 的 liblinphone-sdk,build debug sdk 步驟記錄在另一篇

經過有 debug build 的協助之後, crash 的資訊從原本的組合語言變成了 c 語言 ...

Build liblinphone-sdk for iOS

Install git, homebrew

install git, homebew if you have no one.

Clone ios-linphone

$ git clone git://git.linphone.org/linphone-iphone.git --recursive

Remember add --recursive to download submodule

Excute .prepare.py

$ ./prepare.py

You may need execute this command many time until you install all dependecies.

In my case, I installed these tools:

$ brew install imagemagick doxygen cmake intltool yasm automake coreutils wget optipng nasm 
$ brew install intltool

If it works, you will get the following message:

-- Configuring done
-- Generating done
-- Build files have been written to: /Users/cwliu/Dev@Local/WiAdvance/1603_GoodWox/liblinphone/linphone-iphone/WORK/ios-armv7/cmake
INFO: You ...

Using Haneke for Image Cache in Swift

如果要在 iOS 上,圖片是從網路下載回來的話,勢必要需要做快取,以避免每一次顯示都要重新載入,今天要介紹一套叫 Haneke的 Swift Library, Haneke 是使用 extension 的方法讓 UIImageView 多了一些方法可以做快取。

首先, 安裝可以透過 CocoPods,這邊不多詳述。使用之前記得要先 import:

import Haneke

如果想顯示一張網路上的圖片: http://i.imgur.com/thfn9Ml.jpg,最簡單用法就是

imageView.hnk_setImageFromURL("http://i.imgur.com/thfn9Ml.jpg")

它就會幫你做完下載、快取、重載的動作,相當的方便。另外,若想刪除所有的 image ache,可執行:

Haneke.Shared.imageCache.removeAll()

另外比較進階的用法,像是有一些圖片需要帶 HTTP Header 才有權限存取的話,這邊以加一個 Authorization 的 header 為例,先新增一個自訂的 NetworkFetcher

public class BearerHeaderNetworkFetcher<T: DataConvertible> : NetworkFetcher<T> {

    var token: String

    public override var session : NSURLSession {
        let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
        configuration.HTTPAdditionalHeaders = [
            "Authorization": self.token
        ];

        return NSURLSession(configuration: configuration)
    }

    override init(URL : NSURL) {
        self.token ...

在iOS/Swift中使用 liblinphone 函式庫

本文記錄了我在 ios 上面使用 Liblinphone 的過程。

基於 Github basefx/linphone-swift 上面的這個專案,StackOverflow 討論 為基礎來修改的。另外,我把這篇的結果也放到 github 上面給大家參考: https://github.com/cwliu/linphone-swift-demo

把 linphone iOS 加入 Swift 的 Project

下載 liblinphone SDK: http://www.linphone.org/releases/ios/liblinphone-iphone-sdk-latest.zip

解壓縮之後,裡面是一個liblinphone-sdk的資料夾,把這個資料夾複製到 swift 的專案之中。

新增 objective-c bridging header

因為 liblinphone 是 c 的 library,所以要在 swift 的專案中使用的話,要設定bridging header。在 Project Navigator中新增一個 .h Header 設定一個檔名,例如 linphone-swift-demo-Bridging.h。並在 project setting 的 Build Settings > Swift Compiler - Code Generation 中設定Objective-C Bridging Header為這個檔案:

linphonedemo3/bridge.h

http://i.imgur.com/N5UbxNy.png

在這個檔案中加入以下的內容:

#import "linphone/lpconfig.h"
#import "linphone/linphonecore.h ...

使用 Liblinphone Android SDK 撥打 SIP 電話

前言

如果想在 Android 上開發 SIP 應用的話,可以考慮 Linphone 推出的 SDK 叫 liblinphone,這是一套開源的 SIP 套件,採用 GPLv2 授權,目前由Belledonne Communications公司所維護。

這篇簡單介紹一下在 Android 上面開發 Linphone 的關鍵步驟

下載 liblinphone SDK for Android

此時最新的版本是 2.5.0: https://www.linphone.org/releases/android/linphone-android-sdk-latest.zip

解開下載回來的 zip:

├── armeabi
│   └── liblinphone-armeabi.so
├── armeabi-v7a
│   ├── libffmpeg-linphone-arm.so
│   └── liblinphone-armeabi-v7a.so
├── linphone.jar
└── x86
    ├── libffmpeg-linphone-x86.so
    └── liblinphone-x86.so

包含了 linphone.jar 跟其它的 so 檔案。這是因為 liblinphone 底層主要還是由 C/C++ 語言組成,而透過用 jni 的方式來讓 java 程式可以使用。

Android Studio 設定

在預設的 build.gradle 之中,因為都有包含

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
}

所以最簡單的方式就是把 linphone.jar 放到 libs 資料夾中(跟 ...

使用 Style 或 Theme 修改 Android 元件的外觀

前言

在 Android 中有 styletheme 兩種不同方式來設定元件的外觀

Style

res/values/styles.xml 新增一個 style 標籤,讓View的背景顯示為深藍色:

<resources>
    ...
    <style name="BeatBoxButton">
        <item name="android:background">@color/dark_blue</item>
    </style>
</resources>

使用方式則是在想套用這個 stytle 的 view 物件上加上 style 屬性:

<Button
    ...
    style="@style/BeatBoxButton.Bold"/>

這麼做的好處就是當應用程式如果有很多 button,若是要換別的顏色的話,就只要更新 style 就好了。

Style inheritance

另外 style 跟 class 一樣有繼承的使用方式

方法一:

加上 parent 的屬性:

<style name="MyButtonStrong" parent="MyBoxButton">
    <item name="android:textStyle">bold</item>
</style>

方法二:

在 Parent 的名稱後面直接加上 .,例如: "MyButton.Bold"

<style name=MyBoxButton.Bold">
    <item name="android:textStyle">bold</item>
</style>

兩這種方法都可以達到 style inheritance 的效果

Theme

針對整體性的 style,如果 app 有 ...

解決開啟 android emulator 記憶體用量不足的問題

最近 Android 2.0 新推出 Emulator 比過去的效能好很多,所以就從用 Genymotion 改回用 Google 的 Emulator,但是在開發的時侯,發生一個小問題,在我的 Mac 上面沒辦法同時間開多個 Emulator,會出現以下錯誤訊息:

emulator: The memory needed by this VM exceeds the driver limit.

HAX is not working and emulator runs in emulation mode

在 OSX 的解決方案如下:

找到 Android SDK 裡面的 android-sdk-macosx/extras/intel/Hardware_Accelerated_Execution_Manager 資料夾裡面有一個 HAXM installation執行檔,可以重新安裝 HAXM(Intel Hardware Accelerated Execution Manager),增加記憶體用量:

:::bash
$ ./HAXM\ installation -m <最大記憶體使用量>

例如,我想同時間開啟 Nexus 5X,跟 Nexus 5P。這兩支各別都是 1.5 GB的記憶體使用量,所以需要把 HAX 增加到 3072MB:

:::bash
$ ./HAXM\ installation -m 3072

安裝完成之後就可以同時開兩個 Android emulator 了:

nexus5x-neux5p

在 Genymotion 的 Android 6.0 Marshmallow 裝置上安裝 Google Apps

genymotion

Android Studio 官方有 AVD(Android Virtual Device),運作在 QEMU 的 Emulator 之上,使用上效率不好,所以近期開發 Android 都是使用 Genymotion 這套 Android emulator(仿真器)上。Genymotion 是基於 VirtualBox 基礎上,而 Genymotion 上的 virtual device 預設沒有Google Play、Google Maps 等 Google Apps。如果想要在上面裝 Google Apps,需要以下額外的設定:

註: 如果要安裝 gapps 在 Genymotion 推出的 PREVIEW - Google Nexus 5X - 6.0.0PREVIEW - Google Nexus 5P - 6.0.0話,則需要額外的步驟:

  1. 安裝 Genymotion-ARM-Translation_v1.1.zip,重啟裝置

install-1

install-2

  1. 安裝 gapps-L-4-21-15.zip
  2. 先登入 Google 帳號
  3. 安裝 benzo-gapps-M-20151011-signed-chroma-r3.zip,重啟裝置

google-play

這樣就有 Google Play 可以用了