2014年3月20日 星期四

Android 開發 (三十三) 遠端 Service AIDL 的使用

假設今天有兩個app要互相傳遞資料

例如

我有兩個書本定閱app ,這兩個app的書單必須同步,要如何做到?

可以使用AIDL(Android Interface Definition Language),這可以讓我們同時access同一個service,
所以接下來我想做的事情是
1. 建立兩支app存取的interface 以及model
2. 建立 兩支app
3. 建立 一個service


首先必須先建立interface,這邊可以使用android內建的方法,我們只需要創建好.aidl檔之後
android會幫我們建好.java檔,


可以看到在上圖的interface裡面,我有使用自己建立的Book , aidl 可以import 繼承自parceable的物件,不過繼承的物件也必須有自己的aidl檔
如下圖 book.aidl


接著我們必須建立兩支app ,然後使用bindservice將interface取回

  conn = new MyServiceConnection();
  bindService(intent, conn, Context.BIND_AUTO_CREATE);

在ServiceConnection中我們可以使用 asInterface將我們需要的interface 取回

 class MyServiceConnection implements ServiceConnection{

  @Override
  public void onServiceConnected(ComponentName name, IBinder service) {
   manager = BookListManager.Stub.asInterface(service);
   
  }

  @Override
  public void onServiceDisconnected(ComponentName name) {
   manager = null;
   
  }
  
 }

在取得interface之後,我們就可以使用相關的method


在建立好兩支app之後,接著就只需將Service建立完成即可
如下圖在binder裡將interface.stub回傳回去,使mainactivity可以取得service的interface



這樣就完成了,只需要在一開始startservice之後就可以共享資料了。

在這邊必須注意一點,
就是兩個app的aidl檔必須完全一致,包含package name
如下圖

否則會出現
SecurityException: Binder invocation to an incorrect interface 這個錯誤

接著附上sampleCode

2014年3月8日 星期六

crashlytics crash分析工具

在開發專案時常常會聽到一句話
                                           
                                                   "在我那邊是好的阿"

相信上面這句話道出了很多開發人員的心聲,而我也常常身受其害,
有很多BUG在自己的機台上就是不會發生,可是每次到了使用者或老闆手上就特別容易發生,我相信他們身上一定有一些奇怪的磁場?!

回歸到正題,如果無法複製問題那就無法解決問題,但是問題總是要解決的,如果沒有合適的工具那要怎麼解決,以前只能瞎子摸象,他們說這樣會crash阿,我就手動壓力測試,測個30分鐘,沒問題只好說沒看到,希望有人可以給出個複製步驟,如果沒有就只好祈禱不要再出現,現在想想當時還真的很厲害,瞎子摸象還真的讓我摸出一隻動物出來....。

最近使用了crashlytics,他可以用來分析crash發生的頻率、版本以及發生exception的位置,
這對開發人員來說實在是太棒的消息了,試想...我release出一個版本給龐大的QA使用者們
測試使用,他們還會回報BUG在哪(如果這樣做我相信明天老闆就會叫我走人....)。


要使用crashlytics其實很簡單,只需要前往他們的網站,然後根據他們的步驟


完成安裝之後,接著只要照著他的步驟設定就可以了,如果一直卡在連結app那邊可以考慮使用firefox瀏覽器來run。


之後就可以等著廣大的QA使用者們把crash結果一個一個回報過來囉~~
下圖是一個簡單的範例,其中發生exception的method 由於我們使用proguard加密過app所以無法直接看出是哪個function name,不過我們可以透過mapping.txt對照出相對的名稱。

有了這個工具,開發人員就不再有藉口說我這邊都是好的了......
不過,工具不是萬能的,這個工具也只能告訴我們crash發生的點,multi-thread才會出現的bug,還是需要想點辦法才能複製出來。


2014年3月3日 星期一

Git(八) 還原被修改的檔案

今天要談的是如何還原被修改的檔案,檔案被修改之後有分成兩種情況

  1. 修改的檔案尚未被push上remote端
  2. 修改的檔案已經被push上remote端

修改的檔案尚未被push上Remote端




如上圖,我在local端做了一些修改做了3個commit ha, hb, hc
但是我尚未push 到remote端,這時候我發現hb這個commit 改了我不希望被更動的東西,我希望remove hb這個commit ,這時候可以使用 git rebase -i  HEAD_SHA  (其中 HEAD_SHA = origin/HEAD的 SHA)

接著會出現如上圖,這時候只需要將 hb這行刪除就可以了。
然後就會看到
hb這個commit 已經消失了。


如果只是想要移除上一個commit 例如  我commit 了ha hc  ,然後我希望將hc這個commit 移除
這時候也可以直接使用 git reset --hard HEAD^ 這樣就會將版本退回ha commit 
對reset這個command有興趣的話可以參考

Git 常用指令 (一) git reset

Git 常用指令 (五) reset 應用 merge 和 rebase之後的倒回


上面的方法很方便,但是這些方法僅限於使用在commit 尚未被push到remote端之前
假設commit 已經被push到remote端這就麻煩了,就只能只用下面的方式來修改。


修改的檔案已經被push上Remote端

如下圖,假設我commit並push了 ha 到remote端上

在我commit之後我希望reverse這個commit ,這時候可以使用
git revert  ha_SHA  (其中 ha_SHA為 ha這個commit 的SHA)
這樣就可以將 ha這個commit reverse 。


假設我今天merge 了一個branch helloo,但是在merge之後後悔了,希望將這個merge revert
如下圖

這時候我必須使用 git revert -m 1 Merge_Branch_helloo_SHA
(其中 Merge_Branch_helloo_SHA的 SHA為 merge branch helloo的SHA)

假設未來希望將revert merge的版本還原,就必須再一次revert版本(merge branch將不會work),
這樣就能將原本的版本覆原。


使用git 還原的時候要確切的知道自己在幹嘛,如果不是很確定的話,記得做備份的動作,否則一不小心可能會將寫好的檔案revert掉。









2014年2月24日 星期一

如何不透過email 傳送資料給自己的手機或電腦


不要再使用email傳送檔案給自己了,使用pushbullet吧!!

甚麼是pushbullet?

當你在手機上有一些資料想要傳到電腦或者有些資料想從電腦傳到手機時,
通常我們都會用facebook ,email 或 藍芽 ....等方式傳資料給自己。
pushbullet想做的事情很簡單


用最好理解的方式說明,你可以把他想成是可以跟自己對話的 line or whatsapp


現在介紹pushbullet

登入之後會出現上方的圖,只要在自己的裝置上安裝他專屬的app 就可以傳送檔案,文件,文字了,在chrome上必須安裝extension。

pushbullet還支援api,有機會再來分享這部份給大家




2014年2月17日 星期一

Android 開發 (三十一) layer-list 使用

Layer-list 讓我們可以層疊客制多層的layer,由於android手機的解析度非常眾多,這對UE來說是非常大的負擔,很難用一張圖來滿足所有的解析度,通常比較簡單的button 或線都會用畫的,這樣的好處是,圖的解析度比較不會跑掉,只是這也就苦了RD了。


如何使用layer-list?

如下方的按鈕

<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >

    <item>
        <shape android:shape="rectangle" >
            <corners android:radius="10dp" />

            <solid android:color="#2caabb" />
        </shape>
    </item>
    <item
        android:bottom="3dp"
        android:left="3dp"
        android:right="3dp"
        android:top="3dp">
        <shape android:shape="rectangle" >
            <corners android:radius="10dp" />

            <solid android:color="#222244" />
        </shape>
    </item>
    <item
        android:bottom="7dp"
        android:left="7dp"
        android:right="7dp"
        android:top="7dp">
        <shape android:shape="rectangle" >
            <corners android:radius="10dp" />

            <solid android:color="#333333" />
        </shape>
    </item>
    <item
        android:bottom="9dp"
        android:left="9dp"
        android:right="9dp"
        android:top="9dp">
        <shape android:shape="rectangle" >
            <corners android:radius="10dp" />

            <solid android:color="#2cbb77" />
        </shape>
    </item>

</layer-list>

每個item都代表一層
上面那張圖是由四層圖層疊出來的
corners使方型的角變成圓角
shape 擁有四種形狀  ["rectangle" | "oval" | "line" | "ring"

更詳細的說明可以觀看 android developer的網址
http://developer.android.com/guide/topics/resources/drawable-resource.html#LayerList

Android 開發 (三十) Selector 使用

Selector讓我們可以客製化我們想要的UI色彩,
例如我希望按鈕在正常的情況下是灰色,在按下去時為藍色
又或者我希望checkbox在正常的情況下是灰色,被check的時候是藍色
要實作這個功能首先必須先在drawable-xxxx folder中創造一個

myselector.xml

<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:drawable="@color/mycolor1" android:state_pressed="true"></item>
    <item android:drawable="@color/mycolor2" android:state_pressed="false"></item>

</selector>

在上面的程式裡,我設定當view 的state為 pressed的時候  會顯示 mycolor1的drawable
當view的state為 not pressed的時候,會顯示mycolor2的drawable。

接著只需要設定 android:background="@drawable/myselector" 之後當客製化色彩的button就完成了

接著要客製化checkbox

checkboxselector.xml


<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:drawable="@color/mycolor1" android:state_checked="true"/>
    <item android:drawable="@color/mycolor2" android:state_checked="false"/>
    <item android:drawable="@color/mycolor2"/>

</selector>

上面的程式碼設定了當view 被 check的時候 顯示mycolor1 ,沒有check的時候顯示mycolor2
, 預設的色彩為 mycolor2
接著只需要設定 android:background="@drawable/checkboxselector"  就完成了

使用selector讓我們可以設定不同state時我們想要的色彩或者圖案。
在android developer網頁有更詳細的描述
http://developer.android.com/guide/topics/resources/drawable-resource.html#StateList

2014年2月16日 星期日

Android 開發 (二十九) imagelevel

為何要使用setimagelevel?

在設定圖片時,android 有一種方式讓我們可以在不同的level顯示不同的圖片,
這樣的好處是不需要重新去尋找圖檔,只需要在一開始做好設定,之後就利用定義好的level去切換就好了,例如  press 就是 level 1     release 就是level 2   check就是level3 ... etc


要如何使用setimagelevel的功能呢?

首先,我們必須先設定level-list  如下

imagelevel.xml
<level-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:maxLevel="1" android:drawable="@drawable/c" />
    <item android:maxLevel="2" android:drawable="@drawable/b" />
    <item android:maxLevel="3" android:drawable="@drawable/d" />
    <item android:maxLevel="4" android:drawable="@drawable/e" />
    <item android:maxLevel="5" android:drawable="@drawable/a" />
</level-list>

接著設定imageview的src


    <ImageView
        android:id="@+id/img"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/imagelevel" />

接著只需要在條件符合時呼叫 setImageLevel(1)   or  setImageLevel(2)
這樣就可以讓圖片隨著不同的state變更圖片了,這樣的好處是,這個頁面的圖片一目瞭然,
看程式的時候不再需要整個程式碼一張一張尋找了。