2016年8月30日 星期二

HackerRank Jumping on the Clouds(Algorithms>Implementation)

題目:
Emma在玩一個新的手機遊戲,裡面有n朵雲,
分別從0~n-1將之編號。
玩家開始時在C0的雲朵,每次可以跳1或2朵雲的高度,
最終目的是到達Cn-1的雲朵。

雲朵分兩類,正常雲和雷雲,
雷雲踏上去就會game over,
Cn-1和C0保證是正常雲,
跳到Cn-1則遊戲獲勝。

輸入:
第一行輸入總共的雲朵數n,
第二行輸入n個用空格隔開的integer,
從C0到Cn-1,當中以數字0代表正常雲,
數字1代表雷雲。
本題輸入條件會保證總是有遊戲獲勝的可能性。

輸出:
最少次數能跳到Cn-1的解。

解題:
當限制遊戲保證有獲勝可能性時,
問題便大幅簡化,
因為一次最多跳2層,
也就表示不會2層都是雷雲。
那麼只要每次都檢查能否跳2層,
可以的話就跳2層,否則就跳1層,
並更新cnt數,就可以輕鬆得到最少次數的解了。

code裡面由於迴圈條件每次會++,
故在跳2層時只要將i再額外加1即可。


Code:
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
#include <stdbool.h>

int main(){
    int n; 
    scanf("%d",&n);
    int *c = malloc(sizeof(int) * n);
    for(int c_i = 0; c_i < n; c_i++){
       scanf("%d",&c[c_i]);
    }
    int cnt = 0;
    for(int i = 0; i+1 < n; i++){        
        cnt++;    
        if((i+2) < n)
            if(c[i+2] == 0)
                i++;
    }
    printf("%d", cnt);
    return 0;
}

HackerRank Maximizing XOR(Algorithms>Bit Manipulation)

題目:
給定L和R兩個integer,找出L和R之間最大的A xor B,
當中A和B滿足 L<=A<=B<=R。

輸入:
兩行分別輸入L和R,
限制為1<=L<=R<=10的3次方。

輸出:
輸出如題所述的值。

解題:
基本上使用兩層的巢狀迴圈即可找出最大值,
唯獨要注意的是,
因為bitwise xor的符號"^"在編譯器的優先序會低於">"和"<",
故記得將其用括號包起來。

Code:
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <assert.h>
/*
 * Complete the function below.
 */
int maxXor(int l, int r) {
    int max = 0;
    for(int a=l; a<=r; a++)
        for(int b=a; b<=r; b++)
            if((a^b) > max)
                max = (a^b);        
    return max;
}
int main() {
    int res;
    int _l;
    scanf("%d", &_l);
    
    int _r;
    scanf("%d", &_r);
    res = maxXor(_l, _r);
    printf("%d", res);
    
    return 0;
}

HackerRank Day 0: Mean, Median, and Mode (Tutorials>10 Days of Statistics)

題目:
輸入n個正整數的陣列X,
輸出其平均值,中位數及眾數。
(如有多個眾數則取最小者)

輸入:
第一行為數字n,代表陣列的個數。
第二行為以空格隔開的n個正整數。
輸入限制10 <= N <= 2500,且每個正整數<=10的5次方。

輸出:
分三行輸出平均值(mean),中位數(median),眾數(mode),
如解為小數,則輸出到第1位。

解題:
首先讀入後,先經過排序由小至大。
(這邊還是使用之前用過的qsort)

平均值->加起來除以n即可。

中位數->取n/2,整除的話,
答案是為x[n/2-1]+x[n/2+1-1]的一半,
否則解為x[(n+1)/2-1]。
(-1的原因是因為陣列由0開始,全部平移1單位)
留意%0.1lf可以保證輸出的小數點後面顯示1位。

眾數->在輸入值有限的狀況,使用類似bucket sort的方法。
直接開一個every_cnt[100000]並初始化,
接著依次讀出x[i]的值,並以every_cnt[x[i]]++達到記數的效果。
最後,遍歷各項有值的every_cnt,
經比較即可得出眾數為何。

這個方法較為占用記憶體,但除去前面sorting的部分,
後面進行記數以及查找均為線性的複雜度。
(記數為O(n),查找為遍歷x[0]~10^5)


Code:
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>

int compare(const void *arg1, const void *arg2){
     return  (*(int *)arg1 - *(int *)arg2);
}

int main() {
    int n;
    scanf("%d\n", &n);
    int x[n];
    double mean = 0.0;
    for(int i = 0; i < n; i++)
    {    
        scanf("%d\n", &x[i]);
        mean += (double) x[i];
    }
    mean /= (double) n;
    printf("%0.1lf\n", mean);
    qsort((void *)x, n, sizeof(int), compare);    
    
    if(n % 2 == 1)
        printf("%d\n", x[(n+1)/2 - 1]);
    else
        printf("%0.1lf\n", (double)(x[n/2 - 1] + x[n/2+1-1])/2.0);
    
    int every_cnt[100000] = {0};
    int max_n = x[0];
    for(int i = 0; i < n; i++){
        every_cnt[x[i]]++;
    }
    
    for(int j = x[0]; j < 100000; j++)
    {
        if(every_cnt[j] == 0) 
            continue;
        if(every_cnt[j] > every_cnt[max_n])
            max_n = j;
    }    
        
    printf("%d\n", max_n);
    
    return 0;
}

2016年8月28日 星期日

HackerRank Non-Divisible Subset(Algorithms>Implementation)

題目:
給定一個由n個不同integer所成之集合S,
印出最大的子集合S',當中S'必須符合以下條件:
S'中任意2元素之和無法被k所整除。

輸入:
第一行分別給入n, k,用空格隔開。
第二行給入n個數字,代表這個集合的所有元素。

輸出:
印出符合前述之最大可能的子集合S'的大小。

範例輸入:
4 3
1 7 2 4
輸出則為
3

解題:
思路請參照
http://cs.stackexchange.com/questions/57873/maximum-subset-pairwise-not-divisible-by-k

簡單來說,2個數的和能被k整除的話,
代表它們除以k的餘數和也能被k整除(同餘定理)。
舉例來說:
a = bk + c, d = ek + f
a+d = k(b+d) + c+f
前項當然能被k整除,那麼a+d能不能被k整除,
就要看c+f能不能被k整除。

知道這點的話,那麼除以k的餘數可能為0~k-1,
我們可以先分類記錄成一個陣列,
用來表示除以k的餘數為s_i的話,
num[s_i]有幾個。

當k是奇數的時候,兩個數要加起來能被k整除的話,
必然是一個比k/2小,一個比k/2大。
於是遍歷從1到比k/2小的整數,
for(int i = 1; i < k/2; i++)
檢查是num[i]比較大呢,還是num[k-i]比較大呢?
因為兩個互斥,我們就取比較大的放入S'中。

接著留意k是偶數的時候,由於餘數是k/2的話,
兩個一配起來就可以被k整除了,
所以在num[k/2]>0的狀況仍然只能取1個進S'中。
同樣的,餘數是0的狀況下也只能取1個進S'中。

由於在計算時k/2比較特殊,下面的code中有特別分開來計算,
請參閱下方的code。

另外特殊的case為n只有1個或k剛好是1的狀況,
這時候就只能取1個了!

這題在從頭仔細思考過一遍以後,
其實並不算太過複雜,
根本核心在於同餘的概念,
以及如何處理k/2的case。
難怪雖然是Easy Level,答對率卻並不是太高。

Code:
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>

int main() {
    int n, k, result=0;
    scanf("%d %d",&n, &k);
    // Special case: 1. integer num only 1 -> result = 1; 
    //               2. divisor k = 1 -> result = 1
    if(n == 1 || k == 1){
        printf("%d", 1);
    }else{    
        int s_i, num[k];
        for(int i = 0; i < k; i++) 
            num[i] = 0;
        // Store num of those whose remainder is k' at num[k'].
        for(int arr_i = 0; arr_i < n; arr_i++){
           scanf("%d",&s_i);
           s_i %= k;
           num[s_i] += 1;
        }

        for(int i = 1; i < k/2; i++){
            if(num[i] > num[k-i])
                result += num[i];
            else
                result += num[k-i];
        }
        if(num[0] > 0) result++;
        if(k % 2 == 0){ 
            if(num[k/2] > 0)
                result++;
        }else{
            if(num[k/2] > num[k/2 + 1])
                result += num[k/2];
            else
                result += num[k/2 +1];
        } 
        printf("%d", result);
    }           
    
    return 0;
}

HackerRank Cut the sticks(Algorithms>Implementation)

題目:
給定N根樹枝,每根的長度均為正整數,
每次進行cut的操作直到所有的樹枝都被削減到最小的長度。
假設我們有6根樹枝,長度如下:
5 4 4 2 2 8
在一次cut的操作中,我們將6根樹枝都減去2的長度,
在下一次cut的操作之前就只有4根樹枝留下(非0長度的樹枝),
其長度為:
3 2 2 6
重複上述的操作直到沒有樹枝留下。

輸入:
第一行包含1個integer N。
下一行為N個integers:a_0, a_1, ... a_N-1,以空格空開,
代表各樹枝的長度。

輸出:
在每次的操作中,印出當次有幾根樹枝被cut。

解題:
第一次肯定是全部的樹枝都會被cut,
而被cut成0的樹枝,就是當下長度最小的那幾根。
故,只要我們將樹枝由小到大排列,
就可以知道每次會被cut成0的樹枝數,
也就知道每次有幾隻樹枝會被cut。
我們直接使用ANSI C中的qsort進行排序。

qsort要分別提供陣列pointer,陣列長度,
陣列元素的大小,以及比較大小用的function。

底下這邊使用cut_num來計算每次cut有幾隻樹枝被cut掉,
再逐次以remain_num扣掉並印出來。

Code:
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
#include <stdbool.h>

int compare(const void *arg1, const void *arg2){
     return  (*(int *)arg1 - *(int *)arg2);
}

int main(){
    int n; 
    scanf("%d",&n);
    int arr[n];
    for(int arr_i = 0; arr_i < n; arr_i++){
       scanf("%d",&arr[arr_i]);
    }
    qsort((void *)arr, n, sizeof(int), compare);
    int remain_num = n, cut_num = 1;
    printf("%d\n", remain_num);
    
    for(int i = 1; i < n ; i++){
        if (arr[i] > arr[i-1]){
            remain_num -= cut_num;
            printf("%d\n", remain_num);
            cut_num = 1;
        }else {
            cut_num++;
        }
    }
    return 0;
}

HackerRank Angry Professor(Algorithms>Implementation)

題目:
一個教授有一班N個學生的離散數學課,
由於學生缺乏紀律讓他感到很挫折,
玻璃心破碎的他決定如果出席的人數少於K人的話,
他就不上課了!

輸入data:
給定T個testcases,N(學生數量),K(是否上課的門檻人數)
以及每個學生到課的時間點(小於0早到,大於0遲到)。
注意等於0仍視作在上課前到課。
例如:
2
4 3
-1 -3 4 2
4 2
0 -1 2 1
表示有兩個test case,
case1:
4名學生,3名以上開課,
前2名學生早到,後2名學生遲到。
case2:
4名學生,2名以上開課,
前2名學生分別準時及早到,後2名學生遲到。

輸出:
如果該case為取消上課就印出YES,
否則印出NO,
如上例輸出應為
YES
NO

解題:
網站預設C Code讀進來的的陣列a[n]會在迴圈中被重置,
故直接在迴圈內進行判斷,
計算早到+準時到的學生數量(cnt),
如果k > cnt則此testcase為取消上課,
紀錄到陣列result中,
隨後在外面判斷進行印出YES/NO出來即可。

Code:
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
#include <stdbool.h>

int main(){
    int t; 
    scanf("%d",&t);
    bool result[t];
    for(int a0 = 0; a0 < t; a0++){
        int n; 
        int k; 
        scanf("%d %d",&n,&k);
        int a[n], cnt = 0;
        for(int a_i = 0; a_i < n; a_i++){
           scanf("%d",&a[a_i]);
           if(a[a_i] <= 0) cnt++; 
        }
        if (k > cnt)
            result[a0] = true;
        else
            result[a0] = false;
    }
    
    for(int a0 = 0; a0 < t; a0++){
        if(result[a0])
            printf("YES\n");
        else
            printf("NO\n");
    }    
    return 0;
}

HackerRank Divisible Sum Pairs(Algorithms>Implementation)

題目:
給定一個長度為n的integer陣列a_0, a_1, ... , a_n-1及一個正整數k,
找到並印出總共的i, j組合數目,
當中a_i + a_j可以被k所整除。

解題:
開出雙重迴圈即可遍歷所有組合。
a_0的搭配: a_1, a_2, ... , a_n-1
a_1的搭配: a_2, a_3, ... , a_n-1
以此類推可知,
第一個迴圈的條件為0 ~ n-2,
第二個迴圈的條件為i+1 ~n-1。
(i為第一個迴圈的當次起始值)

Code:
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
#include <stdbool.h>

int main(){
    int n; 
    int k; 
    scanf("%d %d",&n,&k);
    int *a = malloc(sizeof(int) * n);
    for(int a_i = 0; a_i < n; a_i++){
       scanf("%d",&a[a_i]);
    }
    int cnt = 0;
    for(int i = 0; i < n-1; i++)
        for(int j = i+1; j < n; j++)
            if ((a[i]+a[j]) % k == 0) cnt++;

    printf("%d", cnt);
    
    return 0;
}

HackerRank Kangaroo(Algorithms>Implementation)

題目:
給定兩隻在x軸上往正方向移動的袋鼠,
起始座標分別為x1, x2,其速度分別為v1, v2,
當中 0 <= x1 < x2 <= 10000, 1 <= v1, v2 <= 10000,且均為integer.
若兩隻袋鼠有機會同時間在同座標相遇,印出"YES",否則印出"NO"。

解題:
簡單的題目。
先考慮若v1 <= v2時,再怎麼樣也是追不上,可以直接印NO。
接下來就直接計算距離差/速度差能否整除(餘數為0),
即可依此印出YES或NO。


Code:
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
#include <stdbool.h>

int main(){
    int x1; 
    int v1; 
    int x2; 
    int v2; 
    scanf("%d %d %d %d",&x1,&v1,&x2,&v2);
    if (v1 <= v2) {
        printf("NO");
    }else {
        if ((x2-x1)%(v1-v2) == 0)
            printf("YES");
        else
            printf("NO");
    }
        
    return 0;
}

HackerRank Start.

從今天起將會開始不定時解HackerRank的題目,
基本上主體會使用C語言,歡迎有興趣的朋友觀看及給予建議XD
 (因為有時候我解的方式可能也不是最好的)

2016年4月13日 星期三

[Android] Android Studio 2.0 with java8


在實際使用新的Android Studio 2.0後,
發現有好多都不認得了XD
不知道什麼時候冒出來的Gradle Script(天啊我到底埋在Driver層多久了)以外,
然後Android N也有preview了。

在build的時候,
由於電腦環境先前先裝過java7,而後升成java8,
在編譯一個單純的activity時可能會出現類似這樣的錯誤:


Unsupported major.minor version 52.0

經過查詢了一下, 最簡單的方式就是更改指定build的sdk路徑:
File->Project Stucture...

找到SDK Location頁籤中的JDK Location, 將其改成1.8的路徑即可。

當然,如果要降版使用1.7也是可以的,
只是這樣的話就要改Gradle Script.
於build.gradle裡面:

android { 
          compileSdkVersion 19
          buildToolsVersion "19.0.0"
    defaultConfig {
          minSdkVersion 7
          targetSdkVersion 19
    }
    compileOptions {
          sourceCompatibility JavaVersion.VERSION_1_7
          targetCompatibility JavaVersion.VERSION_1_7
    }
}

[Android] 回歸。


好久不見了,不曉得還有沒有朋友在看這個部落格。
最初的想法是將工作前及開始上班後,
所遇到的問題,來為自己整理一份how-to-solve.
但後來隨著忙碌及趕工,疏於回頭整理。
(同時被bug追著跑的感覺很差,尤其被前人的bug,哈哈)

總之呢,
最近應該會有一段比較不那麼緊迫的時間,
因應工作內容也許又要重新回到跟Application層相關的東西,
所以可能會寫一點在執行Android Studio 2.0相關的簡單操作方法吧XD

對於之前留言詢問問題的各位,
已經有一一做回覆,希望雖然有點晚了,
這些思路仍能幫助到您。

(不過話說,Blogger它能不能送留言通知到我email信箱呀?
真的很容易沒注意到有新留言XD)

大概就先這樣~

2015年4月13日 星期一

[Linux] linux搜尋小技巧

一般狀態下我們會用find -iname 來找出指定名稱的檔案或資料夾,
以grep -r 來遞迴式搜尋字串,但grep -r 其實無法非常完整的遞迴,
下面利用xargs將前面使用的資料傳遞到後面當作參數的特性,
來進行較快速且較完整的字串搜尋。

find -iname "*"|xargs grep "reboot" // reboot替代成你想要搜尋的字串

在*處進行一些處理就可以進行其他簡單的篩選。
比如只找c語言的檔案: "*.c"

2013年9月3日 星期二

[Android] Android Developer App Components Note 3

App Fundamentals-The Manifest File 1

(見Android Developer App Fundamentals The Manifest File)

The Manifest File

在Android系統可以開始一個app組件(component)之前,
系統必須要知道這個組件的存在。
怎麼知道呢?就是透過讀這個app的AndroidManifest.xml檔。
你的app必須要把所有的components定義在這個檔案裏頭,
而且這個檔案必須要放在你的Android專案(project)的根目錄。

Manifest除了聲明(declaring)了app的組件以外,
還做了以下幾件事情:
a. 辨認所有這個app所需要的使用者許可授權(user permissions),
比方說像是網路存取,或者是讀取使用者的通訊錄。
b. 聲明這個app所需的最低Android API Level,這是根據這個app用了哪些API。
c. 聲明這個app所需要使用的硬體和軟體功能,
像是相機、藍芽服務、或者多點觸控的螢幕。
d. 這個app所需連結的API libraries(指在Android framework APIs以外的東西),
像是Google Maps library。

Declaring components

Manifest的主要工作就是要告知系統app所用的組件。
舉例來說,一個manifest檔可以聲明一個activity如下:
<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
    <application android:icon="@drawable/app_icon.png" ... >
        <activity android:name="com.example.project.ExampleActivity"
                  android:label="@string/example_label" ... >
        </activity>
        ...
    </application>
</manifest>
 <application> 元素裡,android:icon屬性指向一個用以辨認這個app的圖示的資源。
<activity>元素裡,android:name屬性指定了完全相符的Activity的class的子class名字,
android:label屬性指定了一個字串(string)用以作為使用者可見的activity的標籤(label)。

你必須用這樣的方式來聲明出所有app的組件:
a. <activity>元素-> activities
b. <service>元素-> services
c. <receiver>元素-> broadcast receivers
d. <provider>元素-> content providers

上述4個,除了broadcast receivers以外,就算你將其include在原始碼(source)裡,
但卻沒有在manifest聲明的話,系統是看不見它們的,
結果就是會永遠跑不起來。但broadcast receivers是可以定義在manifest,
或者說動態的在code裡產生(作為BroadcastReceiver 物件),
且藉由呼叫registerReceiver()來向系統進行註冊。

對於如何建構你的app的manifest檔的介紹,
可以參照The AndroidManifest.xml File文件。

Declaring component capabilities

如同前面討論的那樣,在Activating Components裡,
你可以使用一個Intent來開始activities, services, 以及broadcast receivers。
你可以藉由在intent裡外顯地命名目標組件(使用組件的class名字)來達到目的。
但是,intents威力強大的地方是在於intent actions的概念。
使用它,你只要單純描述你想要執行的動作(action)
(另外可以選擇是否附帶上你想要操作的資料),
並且允許系統尋找相對應可以執行action的組件來啟動。
如果有多重的組件可以被intent所描述的動作所執行的話,
則讓使用者選擇使用哪一個來進行操作。

系統辨認可以回應到一個intent的組件的方法,
是藉由對比所收到的intent以及在裝置上其他的app的manifest檔所提供的intent filters。

當你在你的app的manifest檔裡聲明了一個組件時,
你可以選擇性地包進那些聲明組件可以做到的事情的intent filters,
藉此它可以對於從其他app傳出來的intents做出反應。
你可以藉由加入一個 <intent-filter>元素,作為組件的聲明元素的子元素,
來定義intent filter。

舉例來說,一個email的app,當中含有寫新郵件的activity,
可能定義在manifest裡,讓它對於"send" intents有反應(為了要傳送email)。
一個你的app的activity可以作出一個intent,
當中附有"send" action(ACTION_SEND)。
當你使用startActivity()來喚起(invoke) intent時,
這個action會被系統比對和email app的"send" activity相符合,
並且將其啟動。

要了解更多有關作intent filters的細節,
請參照Intents and Intent Filters文件。











2013年8月26日 星期一

[Linux] echo與linux系統相關指令

echo "c" > /proc/sysrq-trigger // 讓系統當機
echo "b" > /proc/sysrq-trigger // 重啟
echo "m" > /proc/sysrq-trigger // 送出memory information (view /val/log/message)
echo "p" > /proc/sysrq-trigger // 送出當下的CPU暫存器和flag的值
echo "t" > /proc/sysrq-trigger // 送出thread information
echo "s" > /proc/sysrq-trigger // 重新掛載所有的文件系統
echo "u" > /proc/sysrq-trigger // 重新掛載所有的文件系統成唯讀

2013年6月10日 星期一

[Android] adb與fastboot

很多時候當adb連不上的時候,
除了檢查接頭是否正確連接以外,
就是得看看裝置是不是不小心進到了fastboot模式了。
在fastboot模式底下的裝置,只有透過fastboot指令才能看到。
fastboot的工具應該可以在Android Developer所提供的bundle裡找到。
幾個常見的指令如下:

fastboot devices #查看處在fastboot模式的裝置
fastboot reboot #讓裝置重新開機
fastboot flash recovery recovery.img #將要刷機的.img檔刷到對應的分區

2013年5月13日 星期一

[Android] 監聽port

在做測試時,我們可以透過連接所謂的UART來進行監聽port,
一般很常用的linux工具為gtkterm,
或者cu。
但cu常常會發生兩種錯誤:
 cu: open (/dev/ttyUSB0): Permission denied
 cu: /dev/ttyUSB0: Line in use

即便使用了sudo,亦無法直接解決。
如果要讓cu順利運作,我們需要如下處理:
1. 將別人鎖住port的檔案給砍掉!
sudo rm /var/lock/LCK..ttyUSB0
2. 將目標的port的擁有者改成uucp(cu的上層指令)
sudo chown uucp /dev/ttyUSB0
3. 最後再使用cu -l來觀看
sudo cu -l /dev/ttyUSB0
但說實在的,如果沒有需要將東西寫到port去的話,
我們可以直接用cat:
sudo cat /dev/ttyUSB0

2013年5月8日 星期三

[Android] adb的一些常用權限和指令

在使用adb的時候,常常會發現一些指令會要求權限,
而一般的機器每次下adb reboot以後,
權限通常也就回歸到一般了,這時候就要透過指令設定一些必要的操作。
列出一些好用的指令如下:
adb root // 取得root權限
// 這兩行在當你需要從device將檔案進行讀寫時需要設定
adb remount
adb shell mount -o remount,rw rootfs
// 將當前的Kernel Log輸出到檔案 
adb shell dmesg > kernelLog.txt 
// 當mBootCompleted=true時,代表已經開機完成進待機畫面了!
adb shell dumpsys power|grep "mBootCompleted=true" 

2013年4月24日 星期三

[Android] 透過adb來檢查開機狀態

在開發的過程中adb可以達到很多事情,
比如狀態查詢、開機紀錄等。
這邊記錄一個小技巧,可以用以檢視實體機器是否已經開機成功,
這在當要做一些自動化測試的偵測時會很有效。
首先確認在Linux或者Windows底下已裝有adb工具,
用傳輸線連接電腦和裝置後,以下面方法來操作:
adb devices // 如果順利連線應可以看到有列出裝置
adb reboot // 將裝置重開
adb shell dumpsys power|grep -i mBootCompleted
最後一行代表將資訊裡的mBootCompleted的該行抓出,
如果目前還在開機中的話,這個值會是fail,
如果已經開到螢幕解鎖前的畫面時,這個值就會是true了。

2013年4月15日 星期一

[Android] Android ApiDemos sample

只是簡單的小技巧,不過還是記起來分享一下,
省得以後忘記XD。
當開發Android app的時候,
我們可以到Developer上找到ADT Bundle,
當中包含了Eclipse和Android SDK(目前應該是Android 4.2 JellyBean-API Level 17)。

但如果你想要看sample的話,
會發現你只能掛上Support13Demos, Support4Demos,
以及SupportAppNavigation這三個Demo。
最主體的那個API Demos會在模擬器開啟來的時候找的到,
問題是你會找不到Source Code = =|||||||
怎麼掛Demo?

File->new->project
->Android/Android Sample Project
->Next->Next就可以選擇三個之一了。
選擇完以後,直接build會有error。
在專案上按右鍵->new->Folder,
取個名字比如說libs。
libs上按右鍵->import->General->File System->Next
Browse->在你載下來Bundle的資料夾裡->sdk\extras\->
看你是掛哪個Demo就去看相對缺哪個lib,選擇那個資料夾。
掛載完之後,不要忘記在檔案上按右鍵->Build Path->
Add to Build Path。
完成! 接下來你應該可以在Referenced Libraries裡看到它。

那麼你又問了:怎麼掛最主要的API Demos?
請將這個連結的檔案載下來:
解壓縮後,在Eclipse裡:
File->new->Project...
Android/Android Project from Existing Code
Browse...
直接選解壓縮出來的samples資料夾,
全部加進來按Finish就完成囉!

2013年4月11日 星期四

[Android] Android Developer Note Text and Input 3

Spelling Checker Framework

(見Android Developer Spelling Checker)

序言:

Android平台提供了拼字檢查的framework,
讓你可以實作並在你的app中存取拼字檢查。
framework是Text Service APIs的其中之一,
由Android平台所提供。

要使用app裡的framework,
你要做一個特別型態的Android service,
用以產生一個拼字檢查器的session物件。
根據你所提供的文字,
session物件會回傳由拼字檢查器產生的拼字建議。

Spell Checker Lifecycle:

下面的流程圖展示了拼字檢查器的服務的生命週期:

要初始拼字檢查的時候,
你的app開始它的拼字檢查服務的實作。
在你的app的clients,比如說activities或者個別的UI元素,
從服務來request拼字檢查器的session,
接著使用session來取得文字的建議。
當client終止它的操作時,它關上它的拼字檢查器的session。
如果必要的話,你的app可以將拼字檢查器的service在任何時間關掉。

Implementing a Spell Checker Service:

要在你的app裡使用拼字檢查器的framework,
將一個拼字檢查器service的組件,
包括了session物件的定義。
你也可以將做為控制設定的選擇性的activity加到你的app。
你必須要加XML metadata檔案以描述拼字檢查服務,
且將適當的元素加到manifest檔上。

Spell checker classes:

使用下列的classes來定義了服務以及session物件:
一個SpellCheckerService的subclass
    SpellCheckerService實作了Service class,
以及拼字檢查器的framework介面。在你的subclass裡,
你必須要實作下面的method:
    createSession()
        一個factory method,
回傳一個SpellCheckerService.Session物件
到要做拼字檢查的client。
    可以看Spell Checker Service的sample app來學習更多這個class的實作。

SpellCheckerService.Session的實作
    拼字檢查器服務提供給clients的物件,
用以讓他們將文字傳到拼字檢查器,並取得建議。
在class裡面,你必須實作下面的methods:

    onCreate()
        被系統呼叫,用以回應createSession()
在這個method,你可以初始化SpellCheckerService.Session物件,
基於現有的locale以及其他。
    onGetSentenceSuggestionsMultiple()
        作確切的拼字檢查。
這個method回傳一個SentenceSuggestionsInfo的陣列,
包括sentences傳到的建議。

    你可以選擇性的實作onCancel(),以處理requests來取消拼字檢查;
onGetSuggestions(),以處理一個單字建議的request;
或是onGetSuggestionsMultiple()
以處理批次的單字建議的requests。

    可以參照Spell Checker Client來學習更多實作這個class的方法。

注意: 你必須將所有方面的拼字檢查實作成非同步且thread-safe。
一個拼字檢查器也許會同時被不同的code上所跑的不同的threads來呼叫。
SpellCheckerService以及SpellCheckerService.Session會自動處理好這件事情。

Spell checker manifest and metadata:

在code以外,你需要去提供適當的manifest檔,
還有一個metadata檔給拼字檢查器。
manifest檔定義了app,service,以及activity給控制設定,
就像在下面片段所展示的那樣。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.android.samplespellcheckerservice" >
    <application
        android:label="@string/app_name" >
        <service
            android:label="@string/app_name"
            android:name=".SampleSpellCheckerService"
            android:permission="android.permission.BIND_TEXT_SERVICE" >
            <intent-filter >
                <action android:name="android.service.textservice.SpellCheckerService" />
            </intent-filter>

            <meta-data
                android:name="android.view.textservice.scs"
                android:resource="@xml/spellchecker" />
        </service>

        <activity
            android:label="@string/sample_settings"
            android:name="SpellCheckerSettingsActivity" >
            <intent-filter >
                <action android:name="android.intent.action.MAIN" />
            </intent-filter>
        </activity>
    </application>
</manifest>

注意要使用service的組件,必須要request BIND_TEXT_SERVICE的permission ,
來確保只有系統結合到service。
service的定義同時也指定了spellchecker.xml的metadata檔,
在下一個section來描述。

spellchecker.xml metadata檔案包含了下面的XML:

<spell-checker xmlns:android="http://schemas.android.com/apk/res/android"
        android:label="@string/spellchecker_name"
        android:settingsActivity="com.example.SpellCheckerSettingsActivity">
    <subtype
            android:label="@string/subtype_generic"
            android:subtypeLocale="en”
    />
    <subtype
            android:label="@string/subtype_generic"
            android:subtypeLocale="fr”
    />
</spell-checker>

metadata指定了activity,讓拼字檢查使用控制設定。
它也定義了拼字檢查的子型態,
在這個狀況下,子型態定義了拼字檢查器可以處理的locales。

Accessing the Spell Checker Service from a Client:

app使用TextView的views,自動從拼字檢查得益,
因為TextView會自動使用拼字檢查器。下面的螢幕截圖展示了這個:


無論如何,你也許也想要在其他狀況裡,
去直接和拼字檢查服務來互動。
下面的流程圖展示了和拼字檢查器服務互動的控制流。

Spell Checker Client的sample app,
顯示了如何去和拼字檢查服務來互動。
在Android Open Source Project裡的LatinIME的輸入法編輯器,
也包含了一個拼字檢查的範例。