2014年5月21日

Android─呼叫wifi setting 頁面

趕快記錄一下,以免以後要用的時候忘記

Intent i = new Intent(WifiManager.ACTION_PICK_WIFI_NETWORK);
startActivity(i);

Android─設定String的樣式好工具 SpannableString

當我們在開發APP時,有時候為了讓UI的顯示豐富性,我們可能在一個String的顯示上,會有
不同的配置

例如:字體的顏色、大小、粗細

又或者是String內的部分內容有 電話號碼 Email帳號

我們又希望點選他可以呼叫對應的應用程式

Android提供了SpannableString這個API可以讓我們達到上述的功能


程式碼如下:
版面配置:
orignaltext  TextView 顯示原始的字串
changetext TextView 顯示經過SpannableString設定的字串內容


    
    
    



String.xml內容如下


    Test_SpannableString
    Settings
    Hello world!
     I am normal word\n
    I am small word\n
    I am big word\n
    my phone number:\n033272345\n
    my email accout:\nkkk@quantatw.com\n
    my website:\nwww.quantatw.com\n


主要程式碼:

public class SpannableStringfordemo extends Activity {
 
  TextView organlTextView = null;
  TextView changeTextView= null;
  SpannableString editstring = null;
  String mixstring;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_spannable_stringfordemo);
  organlTextView=(TextView)findViewById(R.id.orignaltext);
  changeTextView=(TextView)findViewById(R.id.changetext);
        mixstring=(String)this.getResources().getText(R.string.small_word) + (String)this.getResources().getText(R.string.normal_word)+(String)this.getResources().getText(R.string.big_word)+(String)this.getResources().getText(R.string.myphonenum)+(String)this.getResources().getText(R.string.myemail)+(String)this.getResources().getText(R.string.myweb);
        organlTextView.setText(mixstring);
        editstring = new SpannableString(mixstring);
        //size the font size
        editstring.setSpan(new RelativeSizeSpan(0.5f), 0, 15, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  //0.5f mean the half default size  
        editstring.setSpan(new RelativeSizeSpan(2.0f), 32, 46, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  //2.0f mean the double default size
        editstring.setSpan(new URLSpan("tel:033272345"), 64, 73, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);     //deal the number  
        editstring.setSpan(new URLSpan("mailto:kkk@quantatw.com"), 90, 107, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);     //send the mail  
        editstring.setSpan(new URLSpan("http://www.quantatw.com"), 119, 136, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);     //open the website
        changeTextView.setText(editstring);
        changeTextView.setMovementMethod(LinkMovementMethod.getInstance()); //when click intent the app
 }
}


顯示內容:

其實SpannableString還可以對String做更多的變化
大家可以參考此網站,敘述的蠻詳細的


2014年4月21日

Android─adb 下 對modem模組下at command

1) ps 顯示當前運行的應用;
2) Kill -15 2666 殺掉相關的cat 應用程式;
3) stop ril-daemon 停掉ril 後臺, 去掉對AT 埠的佔用;

獲知華為模組映射的的AT埠號 /dev/ttyUSB2;

4)啟動cat 後臺運行
adb shell cat /dev/ttyUSB2

5) 在另外shell 打開後 ,執行
echo -e "at+cops?\r\n" > /dev/ttyUSB2
echo -e "at\r\n" >/dev/ttyUSB2

這時cat 後臺將會列印命令返回資訊.

參考連結
其他參考連結
其他參考連結2

2014年4月14日

Android─取得APP資料大小


YouTube實際存在儲存空間大小
在App info裡面,我們可以得到除了APK的SIZE外,還可以知道APP所儲存的Data與cache的容量。

如果我們想要自己開發一個類似的程式,透過PackageManager我們只能得到APK的SIZE,卻無法得知data size與 cache size。

上網搜尋相關的資訊,找到Android裡有一個class可以取得相關的資訊
android.content.pm.PackageStats


參考連結

但是在SDK裡面並沒有開放此方法可以使用,只有系統有調用的權限
我們並沒有使用的呼叫的權限
此時我們可以透過 Java的Reflection機制,來呼叫隱藏的API
觀看詳細請點此


待整理資料
參考連結
參考連結2
參考連結3
參考連結4



2014年3月21日

Android─如何ping網頁

因為程式需求,想要知道手機目前的wifi連線是否有連接外網的能力
所以求助google大神,結果找到了一行程式碼,就可以判斷網路是否有連外能力
參考連結
程式碼如下
if (InetAddress.getByName("www.google.com.tw").isReachable(5000))
上述程式是看能否在五秒內連結 www.google.com.tw,如果連接上回傳true,反之回傳false
但在後來測試的結果發現,不論wifi是否有對外連線能力,都會回傳false
所以又馬上求助google大神,看問題是出在哪邊
發現網路上有很多人跟遇到跟我一樣的問題
程式碼雖然精簡,但不能正常運作,所以只好退而求其次
找尋是否能有在Android程式下執行ping指令
我找到的程式碼如下
參考連結
Process p1 = java.lang.Runtime.getRuntime().exec("ping -c 1 www.google.com");
int returnVal = p1.waitFor();
boolean reachable = (returnVal==0);
上述程式碼,是對www.google.com.tw ping 一次,如果ping成功會回傳0,失敗會回傳-1
在有連外網路的狀況下的確會回傳0,但在ping不到的情況下,thread會在那一直等待ping的結果

於是我又要求助google大神,結果發現了兩種解法
  1. 設定 ping的參數
  2. //-c 是指ping的次數 3是指ping 3次 ,-w 100  w是以秒為單位的間隔時間,100是指timeout 100秒   
    Process p1 = Runtime.getRuntime().exec("ping -c 3 -w 100 " + str); 
    
    參考連結
  3. 對執行 Process做的動作執行timeout的機制
  4. public static int timeoutInSeconds=5;
    Process p1 = java.lang.Runtime.getRuntime().exec("ping -c 1 www.google.com");
    int retrunVal;
    //取得目前系統時間
    long now = System.currentTimeMillis();
    //timeout時間為5秒
    long timeoutInMillis = 1000L * timeoutInSeconds;
    long finish = now + timeoutInMillis;
    //當p1 alive及timeout還沒發生時,繼續在迴圈中
    while ( isAlive( p1 ) && ( System.currentTimeMillis() < finish ) )
    {
        Thread.sleep( 10 );
    }
    
    public static boolean isAlive( Process p ) {
        try
        {
           //p結束的值
           p.exitValue();
           return false;
        } catch (IllegalThreadStateException e) {
          return true;
        }
    }
    
    上述的程式碼是透過process是否已經取得值加上timeout的機制 來判斷是否真的有ping到網頁 當呼叫isAlive時,會去偵測p是否結束並且有回傳值,如果沒有值發生exception回傳true while迴圈則利用isAlive及時間是否超過timeout時間,來判斷是否取得ping值 參考連結

2014年3月20日

Android ─ Handler sendMessage 與 sendToTargett差異

最近在上網找有關Handler相關資訊的時候
發現了,要發送的Message實體化的方式卻有兩種
  • 如果使用sendMessage方式
程式碼如下:
Message msg=new Message();  
msg.arg1=i;  
handler.sendMessage(msg);  
  • 使用sendToTarget方式
 程式碼如下:
Message msg = handler.obtainMessage();  
msg.arg1 = i;  
msg.sendToTarget();     
上次兩種方式都可以達到相同的目的,將訊息回傳給handler去做後續的處理
都有callback的功用
但是兩者對於程式的資源消耗卻有差別
  • 使用sendMessage,我們需要自己new Message,來取得message
    如此會增加prcoess的儲存空間
  • 使用sendToTarget,採用obtainMessage()方法來取得message,是從系統的MessagePool中取得,並不會增加process的儲存空間

所以採用的obtainMessage來實體化message會是比較有效率的方法

參考連結
參考連結




2014年3月17日

Android─隱藏Action bar

如果在android 4.0以上的版本,我們想要隱藏Action bar
我們可以去專案目錄資料夾values-v14下的styles.xml加入

showHome|homeAsUp|showTitle
showHome|homeAsUp|showTitle
@android:color/transparent

如此則可以隱藏action bar

參考連結1
參考連結2

Android─控制螢幕休眠

當我們程式在執行某個片段的時候,我們想要螢幕不休眠,讓使用者可以看到我們所想要顯示的資訊,例如 轉帳中,程式移除中
我們可以透過下面的程式碼達到我們的要求

首先我們先宣告
PowerManager pm;
	PowerManager.WakeLock wakeLock;

之後在oncreate下,加入
pm = (PowerManager) getActivity().getSystemService(
				Context.POWER_SERVICE);
		wakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK, this.getClass()
				.getCanonicalName());

之後在你想要螢幕不休眠的地方加入
wakeLock.acquire();
//想做的動作

別忘了在做完程序時,加入
wakeLock.release();
不然整個activity都會處於不休眠的狀態下

2014年2月5日

Java ─ Array 基本概念

在Java中,= 運算子用於基本資料型態時,是 將值複製給變數,但當它用於物件時,則是將物件指定給參考名稱來參考,您也可以將同一個物件指定給兩個參考名稱,當物件的值藉由其中一個參考名稱變更 時,另一個參考名稱所參考到的值也會更動

public class AdvancedArray { 
    public static void main(String[] args) { 
        int[] refer = {, 2, 3, 4, 5}; 
        int[] cop1; 
        int[] cop2; 
 
        cop1 = refer; 
        cop2 = refer; 
       for(int i = 0; i ; cop1.length; i++) 
            System.out.print(cop1[i] + " "); 
        System.out.println(); 
 
        for(int i = 0; i ; cop2.length; i++) 
            System.out.print(cop2[i] + " "); 
        System.out.println();
 
        cop1[2] = 8; 
        for(int i = 0; i ; cop1.length; i++) 
            System.out.print(tmp1[i] + " "); 
        System.out.println(); 
 
        for(int i = 0; i ; cop2.length; i++) 
            System.out.print(tmp2[i] + " "); 
        System.out.println();
    } 
 }

執行結果:
1 2 3 4 5
1 2 3 4 5
1 2 8 4 5
1 2 8 4 5

上述的程式碼,三個陣列 refer、cop1、cop2都參考至同一個陣列物件,
所以當上述的程式碼透過cop2更改陣列第2個索引值時,也同時改變的refer、col1的值。

如果是想要copy陣列,而不是參考陣列
Java裡的System類別的靜態方法arraycopy(),提供了copy陣列的函式

System.arraycopy(來源, 起始索引, 目的, 起始索引, 複製長度);

範例程式碼如下
int[] arr1 = {1, 2, 3, 4, 5}; 
int[] arr2 = new int[5];
 
System.arraycopy(arr1, 0, arr2, 0, arr1.length); 

for(int i = 0; i < arr2.length; i++) 
      System.out.print(arr2[i] + " "); 
System.out.println();
執行結果: 1 2 3 4 5 

在Java 版本 1.6之後提供了另一個更方便的copy array函式
在Arrays類別底下提供copyOfRange這個method

Arrays.copyOfRange(src, from, to)

其中from和to分別代表陣列的索引值,換言之,「to-from」則是複製的個數。
int array1[] = {1,2,3,4,5};
int array2[];
array2 = Arrays.copyOfRange(array1, 1, 4);

則array2的內容會是{2,3,4}

參考網址1
參考網址2





Android─Service 如何關閉 Activity

步驟一

我們先在Activity裡面加入一個BroadcastReceiver class 我們命名為close_myself,在onReceive method 裡面加入收到廣播後要做的事情
這裡我們做的就是finsih(),讓activity自行關閉
private final BroadcastReceiver close_myself = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
              finish();                                   
        }
};

步驟二

我們可以在Activity在 oncreate 時先註冊 Broadcast 要接收的名稱─CloseExampleAct
當我們接收到CloseExampleAct,去執行close_myself這個BroadcastReceiver。

@Override
      protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_rtsp_server);
      registerReceiver(close_myself, new IntentFilter("CloseExampleAct"));
      setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}

步驟三

接著,你只需要在Service需要關閉Activity的地方加入下面的程式碼
sendBroadcast(new Intent("CloseExampleAct"));
Service就會送出CloseExampleAct廣播出去,有註冊的Activity收到後,就會做相對應的動作

參考網頁


Android ─ 開機時自動啟動Service

如果我們想要Service是android 一開機的時候就啟動,我們該如何操作呢

步驟 1.

Service按照正常宣告
import android.app.Service;
import android.os.IBinder;
import android.content.Intent;
 
public class ServiceExample extends Service {
      @Override
      public IBinder onBind(Intent intent) {
            return null;
      }
 
      @Override
      public void onCreate() {
            super.onCreate();
                // do something when the service is created
      }

步驟2.

新增一個BroadcastReceiver 類別,在這個 class裡使用 onReceive() 這個方法,來接收Android系統開機時所發送的廣播
當我們收到Intent.ACTION_BOOT_COMPLETED這個廣播時,去Start ServiceExample 這支 Service。
import android.content.Context;
import android.content.BroadcastReceiver;
import android.content.Intent;
 
public class Receive_BootCompleted extends BroadcastReceiver{
     @Override
     public void onReceive(Context context, Intent intent) {
        //we double check here for only boot complete event
        if(intent.getAction().equalsIgnoreCase(Intent.ACTION_BOOT_COMPLETED))
        {
           //here we start the service            
           Intent serviceIntent = new Intent(context, ServiceExample.class);
           context.startService(serviceIntent);
       }
    }
}

步驟3.

接著我們要在manifest宣告權限 use-permission,讓我們的BroadcastReceiver 可以有接收BOOT_COMPLETED 的權限



之後再宣告 Receiver 與 Service


      
            
      



根據這些步驟,service就可以在android開機時自動啟動

注意事項

在Android 3.1之後,如果Service沒有系統權限的情況下
是無法使用BOOT_COMPLETED的權限
如果要使用,必須在專案裡面增加一個Activity
此外在安裝到手持裝置時,還必須手動執行該app
如此Service才能開機時自動啟動

參考網址1
參考網址2
參考網址3



2014年1月8日

Android─透過adb發送BOOT_COMPLETED 啟動service

 
adb shell am broadcast -a android.intent.action.BOOT_COMPLETED

透過上面的指令,就不用重開機器,就可以來測試BOOT_COMPLETED廣播
 
不過在我的開發機上測試 ,機器會重開....QQ