2012年12月24日 星期一

[Gerrit] [Jenkins] 在LDAP auth之下,建立一個內部CI Server使用帳號

要使用Gerrit搭配Jenkins auto build並auto code review/verify使用
需要建立一個Jenkins使用的帳號
若在LDAP auth之下
可使用指令建立內部使用的帳號

ssh -p <port> <host> gerrit create-account \ [--group <GROUP>] \ [--full-name <FULLNAME>] \ [--email <EMAIL>] \ [--ssh-key -|<KEY>] \ <USERNAME>

1). 建立帳號jenkins,指定公鑰
$ cat ~/.ssh/id_rsa.pub  | ssh -p 29418 [Admin Account]@[ip] gerrit create-account --ssh-key - --full-name jenkins jenkins

2). 建立帳號jenkins,指定公鑰,指定名稱為jenkins
$ cat ~/.ssh/id_rsa.pub  | ssh -p 29418 [Admin Account]@[ip] gerrit create-account --ssh-key - --full-name jenkins jenkins



ref:http://gerrit.googlecode.com/svn/documentation/2.2.1/cmd-create-account.html

2012年12月19日 星期三

[git] 開發使用指令

1). 開一個開發/測試使用branch
git branch [test_branch]

2). 移到此branch
git checkout [test_branch]

3). 在開發完後,將變更commit成一筆
git add .
git commit

4). 改壞了要回覆成codebase上的
    4.1). 全部回覆到codebase
            git checkout HEAD .
    4.2). 回覆特定資料夾
            git checkout [folder_name]

5). 紀錄此筆commit id,等等要把這筆commit剪(cherry-pick)過去master branch
git log

6). 切換到master
git checkout master

7). 把剛剛那筆commit剪過來master branch
git cherry-pick [commit-id]

8). push到codebase
git push



※ref: http://blog.luzi82.com/2010/08/git-cherry-pick-rebase.html

2012年12月10日 星期一

[Linux] 無需帳號密碼shell的問題解決

1). 刪掉自己電腦known-hosts文件中儲存的特定ip私鑰
$ ssh-keygen -f "/home/qn_lo/.ssh/known_hosts" -R [ip.ip.ip.ip]:29418

2012年12月7日 星期五

[Linux] vim視窗分割

將vim切割成兩個視窗

1). 水平切割
:new [path/filename]

2). 垂直切割
:vnew [path/filename]

3). 切換視窗
Ctrl+w w

[Linux] 開啟vim預設設定檔

1). 安裝vim
$ sudo apt-get install vim

2). 開啟vim預設設定檔,新增一隻.local檔
$ sudo vi /etc/vim/vimrc.local

3). 將以下內容貼在這隻檔案
" 語法高亮度顯示                                                                                           
syntax on
" 搜尋不分大小寫
set ignorecase
" 搜尋若打小寫,則為不分大小寫;搜尋若有大寫,則為精確搜尋
set smartcase
" 顯示列號
set number
" 標記搜尋到的字串
set hlsearch
" 指標線
set cursorline
" 設定 tab 鍵的字元數
set tabstop=4
" 自動縮排
set autoindent
" 不要留備份檔
set nobackup
set nowritebackup

4). 由於nobackup有時會失效,則再新增一隻檔案
$ sudo vi /etc/vim/_gvimrc
" 不要留備份檔
set nobackup


2012年12月6日 星期四

2012年12月5日 星期三

[Android] device內的folder

1. system/app
裝的app會放在這個目錄
需要可以pull出來
$ adb pull /system/app/[name.apk] .

2. system/lib
需要用到的library

2012年11月30日 星期五

[Linux] 開啟共享資料夾

[方法1]
資料夾點選右鍵[屬性]>[共享]

[方法2]
若出現以下Error message

'net usershare' 傳回 255 錯誤訊號: net usershare: cannot open usershare directory /var/lib/samba/usershares. Error 拒絕不符權限的操作
You do not have permission to create a usershare. Ask your administrator to grant you permissions to create a share.

此為權限問題
使用root權限開啟圖形化介面,以方法1方式修改共享資料夾

點選 “alt + f2″
輸入“gksudo nautilus”
會跳出圖形化介面的資料夾


ref: http://linuxowns.wordpress.com/2008/10/28/share-ubuntu-folders-with-windows-samba/

[Linux] 更改電腦名稱(hostname)

要更改電腦名稱
需修改以下兩隻檔案中
將原有的電腦名稱改成新電腦名稱
改完之後重開機

/etc/hosts
/etc/hostname (第一行)

$ sudo vi /etc/hosts
line2: 127.0.0.1   [hostname]
ex: 127.0.0.1   qn.ubuntu

$ sudo vi hostname
line1: qn.ubuntu

[Android] 在userdebug之下push檔案到read only

在user mode,system等權限為read only,無法push檔案
在userdebug mode及eng mode,權限是打開的
若顯示read only,須先remout後,就可以繼續push

$ adb root
$ adb remount
$ adb push [filename] /system/lib

2012年11月13日 星期二

[Android] 在codebase中build APP

需要放到Android codebase底下build的app

放在package/app或是vendor/3rdparty底下
這樣就會build了
build出來的路徑是out/target/common/obj/APPS

若要build在image中
在device/nvidia/ventana/ventana.mk
增加PRODUCT_PACKAGES += [product name]

2012年11月12日 星期一

[Android] 查看Android device key:app sign key

查看sign什麼key
$ adb shell getprop ro.build.fingerprint

若是Android default的key會顯示test key
但Android要出貨,需過CTS,其中一項會檢測key需用自己創造的key
則會顯示release key

android的app若是需要用到系統權限
則需要用同一把key sign此app
此app才能夠獲得系統權限

sign app for system permission)
$ java -Xmx2048m -jar utils/linux-x86/framework/signapk.jar -w keys/platform.x509.pem keys/platform.pk8 unsigned_app.apk signed_app.apk

2012年11月9日 星期五

[git] clone裸版本庫;下載git server

下載一份git server的形式 (裸版本庫)
非codebase

git server的形式如下
/branches
/hooks
/logs
/objects
/refs
config
description
HEAD

下載:
$ git clone --bare ssh://[git server ip]

2012年11月6日 星期二

[linux][git] 架設Git Server及GitWeb

架設Git Server及GitWeb

1). 安裝ssh server、git-core、apache2、gitweb
$ sudo apt-get install ssh git-core apache2 gitweb

2). 創建放git server資料的使用者帳戶
$ sudo useradd -m -s /bin/bash [account]
$ sudo passwd [account]

※ useradd參數
-m:強制有家目錄
-s:設定shell,預設是/bin/sh


3). 啟動ssh
$ sudo sudo /etc/init.d/ssh restart

4). 創建git project
$ sudo su - [account]
$ mkdir TestProject.git
$ cd TestProject.git
$ git init --bare

5). 修改Gitweb連結路徑
$ cd /var/cache/
$ sudo rmdir git
$ sudo ln -sf [放git project的目錄路徑] git
ex: sudo ln -sf /home/git git

2012年10月29日 星期一

[python] 編碼錯誤解決(UnicodeDecodeError)

錯誤訊息:

Traceback (most recent call last):
  File "./check_notice.py", line 243, in <module>
    file.save('Check_Legal_Notice_Report.xls')
  File "/usr/local/lib/python2.7/dist-packages/xlwt/Workbook.py", line 643, in save
    doc.save(filename, self.get_biff_data())
  File "/usr/local/lib/python2.7/dist-packages/xlwt/Workbook.py", line 618, in get_biff_data
    shared_str_table   = self.__sst_rec()
  File "/usr/local/lib/python2.7/dist-packages/xlwt/Workbook.py", line 580, in __sst_rec
    return self.__sst.get_biff_record()
  File "/usr/local/lib/python2.7/dist-packages/xlwt/BIFFRecords.py", line 77, in get_biff_record
    self._add_to_sst(s)
  File "/usr/local/lib/python2.7/dist-packages/xlwt/BIFFRecords.py", line 92, in _add_to_sst
    u_str = upack2(s, self.encoding)
  File "/usr/local/lib/python2.7/dist-packages/xlwt/UnicodeUtils.py", line 50, in upack2
    us = unicode(s, encoding)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 40: ordinal not in range(128)

--

此為編碼錯誤(UnicodeDecodeError)

Python內部使用unicode編碼
在做編碼轉換時,需先將其他解碼(decode)成unicode
再從unicode編碼(encode)成另一種編碼

Ex1:
print a.encode('utf-8')

Ex2:
sheet.write(row,col,data.encode('utf-8'))

2012年10月26日 星期五

[python] list與dictionary的結合

dictionary能儲存資料以及索引
對整理資料能夠有比較好的架構
但資料卻不是有序的序列
於是可藉由list來幫忙做排序

這篇介紹list中包dictionary,及dictionary中包list的方法

1). list中包dictionary
dict1={key:a}
dict2={key:b}
list=[dict1,dict2]
or
list=[]
list.append(dict1)

2). dictionary中包list
dict={}
dict[key]=list()
dict[key].append(value)

2.1). 新增資料前先檢查有沒有key
if key not in dict:
    dict[key] = list()
dict[key].append(value)



※ref:http://lucaswei.blogspot.tw/2012/05/pythondictxlist.html

[python] 外部指令

python需引用外部指令時,可用以下程式碼

import commands

command_git='cd %s; git log' %(codebase)
log=commands.getoutput(command_git)

[python] iterator與enumerate

enumerate(iterable, start=0)
回傳以 iterable 與連續整數配對的 enumerate 物件, start 為整數的起始值,預設為 0

Ex1:
d = ['Spring', 'Summer', 'Fall', 'Winter']
for i, j in enumerate(d, 1):
    print(i, j)

[output]
1 Spring
2 Summer
3 Fall
4 Winter

Ex2:
for i, n in enumerate([1, 3, 5]):
    print i, n

[output]
0 1
1 3
2 5

2012年10月11日 星期四

[python] 使用xlwt輸出excel檔

1). 下載xlwt
http://pypi.python.org/pypi/xlwt

2). 安裝xlwt
$ cd [下載的xlwt目錄]
$ sudo python setup.py install

3). 輸出excel檔
#!/usr/bin/python
import xlwt  #要先安裝xlwt

file = xlwt.Workbook()  #Work的W是大寫
#table = file.add_sheet('sheet name')  #新建sheet
table = file.add_sheet('sheet name',cell_overwrite_ok=True)  #對同個儲存格可複寫的sheet
table.write(0,0,'test')  #對某個儲存格寫入資料

file.save('demo.xls')  #儲存為excel


[python] 安裝套件方法

2012年10月9日 星期二

[python] 安裝套件方法

在Python中安裝額外套件
先到官網下載
進入到該目錄
sudo python setup.py install

2012年9月21日 星期五

[Linux][ShellScript] grep應用


問題
一個txt內存有檔案路徑列表,對此txt中每一檔案路徑做關鍵字查詢

.
├── file.txt
├── a.txt
├── b.txt
├── c.txt
└── test.sh


解法
$ cat file.txt |xargs grep "keyword"
出來的結果是出現有搜尋到關鍵字的檔名,及關鍵字
path/a.txt:keyword
path/b.txt:keyword

只顯示又搜尋到關鍵字的檔名
$ cat file.txt |xargs grep "keyword" |awk -F: '{print $1}'

[Linux][ShellScript] awk - 取得token, 以符號切割

Data=123:aa bbb c

1). 擷取某個token
Ex1: 擷取第2個token
$ awk '{print $2}' Data

Ex2: 擷取第2.3個token
$ awk '{print $2,$3}' Data

2). 以符號切割,並取冒號之後的字串
$ awk -F: '{print $2} Data'

2012年8月15日 星期三

[Linux][ShellScript] 輸出變數

變數要從母script傳到子script
母script=1.sh
子script=2.sh

1). 在母script export需要的變數
name=John
export name
./2sh

2). 在子script就可以直接用了

[Linux][ShellScript] Shell Script分隔變數

Shell Script

1). 宣告變數:name
name=John

2). 呼叫變數:$name or ${name}
echo $name
echo ${name}

※若變數一起打,沒有用{}區隔,容易有混淆
(X) echo $name_$number  →僅會顯示number
(O) echo ${name}_${number}

2012年8月7日 星期二

[Jenkins][Android] build Android的source環境設置

在Android build code前
需下source build/envsetup.sh設置環境變數
但由於jenkins是用/bin/sh,sh並沒有source的指令
因此需在jenkins指定使用/bin/bash
才可以正確使用source設置環境變數

2012年7月4日 星期三

[Linux] tar壓縮相對路徑之目錄檔案

問題
tar壓縮檔案時,會將給的路徑全都壓縮進去
沒有辦法只壓縮目錄底下的某個子目錄

範例
$ tree
.
└── a
    └── b
        └── c
            └── d.txt

$ tar -jcv -f e.tar.bz2 a/b/c/d.txt
a/b/c/d.txt

→這樣壓縮起來,會把前面的資料夾也壓縮進去

如果我只要壓縮底下的子目錄以下要怎麼做呢?

解法
tar的-C參數,能夠臨時切換目錄
tar -jcv -f [壓縮的檔名] -C [臨時切換的目錄] [要壓縮的目錄或檔案]
$ tar -jcv -f e.tar.bz2 a/b/c/d.txt
↓換成
$ tar -jcv -f e.tar.bz2 -C a/b/c/ d.txt
d.txt

2012年6月27日 星期三

[Linux] 檔案目錄權限

一、使用者
1). Owner
2). Group
3). Other



二、權限分三種
1). Read:4
2). Write:2
3). eXecute:1



三、特殊權限
1). Setuid:4
 (檔案) 設置使文件在執行階段具有文件所有者的權限
2). Setgid:2
 (目錄) 目錄被設置該位後, 任何用戶在此目錄下創建的文件都具有和該目錄所屬的組相同的組
3). sTicky:1
 (檔案) 即使具有write的權限,僅有檔案使用者及root權限者才可以刪除檔案

● 設置方式:加在原本三位權限的最前方
ex: chmod 1777 /tmp




※ note:
$ ll /bin/su
drwxrwxrwt 19 root  root  4096 2012-06-27 11:17 ./
$ ll /usr/bin/sudo
-rwsr-xr-x 2 root root 168800 2011-05-30 14:06 /usr/bin/sudo*
$ ll /tmp/ drwxrwxrwt 19 root  root  4096 2012-06-27 17:39 ./





※ ref:
http://www.lslnet.com/linux/f/docs1/i55/big5368810.htm

2012年6月22日 星期五

[Android] [JAVA] 按鈕監聽


作法
1). 單項標準作法
2). 多項使用switch作法

//=============================================================

1). 單項標準作法

public class DeviceInfo2 extends Activity {
 /** Called when the activity is first created. */
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);
  // 找到元件資源
  Button button_info1 = (Button) findViewById(R.id.main_submit_info1);
  // 設定按鍵觸發的method
  button_info1.setOnClickListener(listDeviceInfo);
 }

 private Button.OnClickListener listDeviceInfo = new Button.OnClickListener() {
  @Override
  public void onClick(View v) {
   // 宣告intent,並指定要啟動的class
   Intent intent = new Intent(DeviceInfo2.this, mService.class);
   // 以startservice方式啟動intent
   startService(intent);
  }
 };
}



//=============================================================

2). 多項使用switch作法

public class DeviceInfo2 extends Activity implements OnClickListener{
 /** Called when the activity is first created. */
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);
  // 找到元件資源
  Button button_info1 = (Button) findViewById(R.id.main_submit_info1);
  button_info1.setOnClickListener(this); 
 }
 @Override
 public void onClick(View v) {
  switch (v.getId()){
  case R.id.main_submit_info1:
   // 宣告intent,並指定要啟動的class
   Intent intent = new Intent(DeviceInfo2.this, mService.class);
   // 以startservice方式啟動intent
   startService(intent);
   break;
  }
 }




2012年6月20日 星期三

[Example] [Android] [JAVA] JNI & NDK應用_BMI

JNI & NDK應用_BMI
JNI會將使用者輸入的身高體重傳到C
真正計算是由C來實作
C會將算完的答案回傳到JAVA
JAVA再將其顯示在UI上

流程方法
藉由java撰寫native method,JNI即可在Java中呼叫C寫的程式
C的程式藉由NDK包成.so檔,就可以被JNI呼叫

程式流程
1). (java) 撰寫native method,不需實做

2). 將寫好的.java檔,編成.class檔,再轉成.h檔

3). (C) 撰寫C程式碼,實做.h中的function標頭

4). 撰寫NDK需要的Android.mk

5). 利用NDK將C程式碼轉成.so檔

6). (java) 利用JNI呼叫C的程式















//=============================================================
[Main.java]
package com.jni;

import java.text.DecimalFormat;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.view.View;
import android.view.View.OnClickListener;
import android.os.Bundle;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class Main extends Activity {
 double height, weight;

 /** Called when the activity is first created. */
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);

  Button button = (Button) findViewById(R.id.button_submit);
  button.setOnClickListener(calbmi);

 }

 private OnClickListener calbmi = new OnClickListener() {

  @Override
  public void onClick(View v) {
   DecimalFormat nf = new DecimalFormat("0.00");
   EditText fieldheight = (EditText) findViewById(R.id.edit_height);
   EditText fieldweight = (EditText) findViewById(R.id.edit_weight);
   
   try {
    height = Double.parseDouble(fieldheight.getText().toString());
    weight = Double.parseDouble(fieldweight.getText().toString());
   } catch (NumberFormatException e) {
    // Toast.makeText(v.getContext(),
    // "Please submit height and weight.", Toast.LENGTH_LONG)
    // .show();
    openOptionsDialog();
   }

   if (height == 0 || weight == 0) {
    openOptionsDialog();
   } 
   else {
    TextView bmi = (TextView) findViewById(R.id.text_result);
    double bmi_value = new Bmi().calbmi(height, weight);
    bmi.setText("Your BMI is " + nf.format(bmi_value));
   }
  }
 };

 private void openOptionsDialog() {
  AlertDialog.Builder dialog = new AlertDialog.Builder(Main.this);
  dialog.setTitle(R.string.dialog_title);
  dialog.setMessage(R.string.dialog_msg);
  dialog.setPositiveButton(R.string.dialog_btn,
    new DialogInterface.OnClickListener() {
     public void onClick(DialogInterface dialoginterface, int i) {
     }
    });
  dialog.show();
 }


}


[Bmi.java]
package com.jni;

public class Bmi {
 public native String stringFromJNI();
 public native double calbmi(double height, double weight);
 static{
  System.loadLibrary("cal_bmi_c");
 }
}




參考資料:
[Android] [JAVA] JNI & NDK

2012年6月19日 星期二

[Android] [JAVA] JNI & NDK


Java Native Interface(JNI)
JNI 是用來讓Java跟別種語言溝通的函式庫
Android中是讓Java及C之間溝通
分為Java Call C及C Call Java

Android Native Development Tools(NDK)
將C code包成.so檔,供Java利用

流程方法
藉由java撰寫native method,JNI即可在Java中呼叫C寫的程式
C的程式藉由NDK包成.so檔,就可以被JNI呼叫

//=============================================================

程式流程
1). (java) 撰寫native method,不需實做

2). 將寫好的.java檔,編成.class檔,再轉成.h檔

3). (C) 撰寫C程式碼,實做.h中的function標頭

3). 利用NDK將C程式碼轉成.so檔

4). (java) 利用JNI呼叫C的程式

//=============================================================

步驟
1). (java) 撰寫native method,不需實做
native method前要加native
要load的.so檔是libcal_bmi_c.so,扣除掉前面的lib及後面的.so

method是calbmi,回傳是double的型態
從Java傳入使用者輸入的height, weight

[Bmi.java]
package com.jni;

public class Bmi {
 public native double calbmi(double height, double weight);
 static{
  //要load的.so檔。去掉開頭的lib,及結尾的.so
  System.loadLibrary("cal_bmi_c");
 }
}

2). 將寫好的.java檔,編成.class檔,再轉成.h檔
Eclipse會自動編成.class檔
進入project的資料夾,新開jni資料夾
將編好的.h檔放在jni資料夾中
$ cd [project資料夾]

$ mkdir jni

$ cd jni

$ javah -jni -classpath [放置class的資料夾] [package].[class]

ex: javah -jni -classpath /home/qn_lo/develop/android/workspace/BmiJni/bin/classes com.jni.Bmi


3). (C) 撰寫C程式碼,實做.h中的function標頭在jni資料夾新增C程式碼檔案
將.h檔的JNIEXPORT複製到C並實作
[com_jni_Bmi.h]
/* DO NOT EDIT THIS FILE - it is machine generated */
#include 
/* Header for class com_jni_Bmi */

#ifndef _Included_com_jni_Bmi
#define _Included_com_jni_Bmi
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_jni_Bmi
 * Method:    calbmi
 * Signature: (DD)D
 */
JNIEXPORT jdouble JNICALL Java_com_jni_Bmi_calbmi
  (JNIEnv *, jobject, jdouble, jdouble);

#ifdef __cplusplus
}
#endif
#endif


[com_jni_Bmi.c]
#include 
#include 
JNIEXPORT jdouble JNICALL Java_com_jni_Bmi_calbmi
  (JNIEnv *env, jobject obj, jdouble cheight, jdouble cweight)
{
 double height,weight,bmi;
 height=cheight/100;
 weight=cweight;
 bmi=weight/(height*height);
    return bmi;
}


4). 撰寫NDK需要的Android.mk在jni資料夾中新增Android.mk
LOCAL_MODULE是編成的.so檔名
LOCAL_SRC_FILES是要編的C程式碼檔名
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := cal_bmi_c
LOCAL_SRC_FILES := com_jni_Bmi.c

include $(BUILD_SHARED_LIBRARY)


5). 利用NDK將C程式碼轉成.so檔
 a). 先到Android NDK下載NDK
 b). 在project資料夾下新建libs的資料夾
  如果有需要,可在Eclipse中在Project按右鍵reflesh
 c). 在Eclipse的Project點右鍵[properties]
  在[Builders]中new一個編譯器,選擇program
  輸入Builder的Name,在Main標籤中,輸入Location及Working Directory


















  在Refresh標籤中,將Refresh resource upon completion勾選
  並選擇Specific resource的路徑為project的libs











  在Build Options標籤中
  勾選Specify working set of relevant resource
  並選擇Specify Resource路徑為Project的jni











 d). 按下Build All的按鈕將C編成.so檔











6). (java) 利用JNI呼叫C的程式在java要呼叫,[放JNI的class]().[native method]
new Bmi().calbmi(height, weight)



參考資料:
http://ironurbane.iteye.com/blog/425513
http://kitty.2y.idv.tw/~enijmax/linux/CLib_Jni.html

[blog] Blogger加SyntaxHighlighter顯示程式碼

SyntaxHighlighter

一套可在blogger中置入整齊的程式碼的工具,僅用網頁的Java即可呈現
支援多種語言及多種風格樣板


















//=============================================================

1). 至官網下載壓縮包,並將script資料夾上傳到網頁空間
或者也可以使用官網提供的Host Version
以下範例使用官網提供的Host Version

2). 到blogger後台,修改html中,找到<b:skin>標籤,將以下程式碼貼在此標籤前



3). 找到標籤,將程式碼貼在此標籤前


4). 要使用時,在文章中用此標籤將程式碼夾起來
..程式碼..


※ brush有很多種,細節請見官網的blush列表
※ 有額外的設定檔可加在標籤內,細節請見官網的configuration
ex:
...

2012年6月8日 星期五

[Android] [JAVA] bindService

bindService可將Activity與Service連接
當連線成功後,會自動呼叫執行這個connection內的onServiceConnected(ComponentName className, IBinder service) function,在這function會接收到由service內的onBinde()所丟出來的Ibinder物件,利用這IBinder物件取得Service物件,就可以直接操作Service內各個public 的method

[Activity]
1). 宣告MyService的變數,用此讀取MyService的資料

2). 宣告ServiceConnection的變數,並撰寫onServiceConnected及onServiceDisconnected的method

3). 使用bindService方法連結Activity及Service

[Service]
1). 宣告MyBinder的變數

2). 定義MyBinder的類別來取得MyService的物件實例

3). 使用onBind的方法綁定Service,返回一個ibinder的對象進行操作

4). 撰寫剩下的onRebind、onUnbind

//=============================================================
[Main.xml]
package com.servicetest2;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

public class Main extends Activity implements OnClickListener {
 private Intent intent;
 private MyService myService;
 private boolean flag;
 private ServiceConnection serviceconnection = new ServiceConnection() {

  @Override
  public void onServiceConnected(ComponentName name, IBinder service) {
   Toast.makeText(Main.this, "Bind Service", Toast.LENGTH_SHORT).show();
   myService = ((MyService.MyBinder) service).getService();
   flag = true;
   Log.d("Main","Bind");
  }

  @Override
  public void onServiceDisconnected(ComponentName name) {
   Toast.makeText(Main.this, "Bind Service Failed", Toast.LENGTH_SHORT).show();
   myService = null;
  }

 };

 public void onClick(View view) {
  switch (view.getId()) {
  case R.id.btnStartService:
   startService(intent);
   break;
  case R.id.btnStopService:
   stopService(intent);
   break;
  case R.id.btnBindService:
   bindService(intent, serviceconnection, Context.BIND_AUTO_CREATE);
   break;
  case R.id.btnUnbindService:
   // 當有bind,才會unbind
   if (flag == true) {
    unbindService(serviceconnection);
    flag = false;
    Log.d("switch","if");
   }
   Log.d("switch","break");
   break;
  }
 }

 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);
  flag = false;

  // 取得資源
  Button btnStartService = (Button) findViewById(R.id.btnStartService);
  Button btnBindService = (Button) findViewById(R.id.btnBindService);
  Button btnUnbindService = (Button) findViewById(R.id.btnUnbindService);
  Button btnStopService = (Button) findViewById(R.id.btnStopService);

  // 設置按下按鈕的物件實例
  btnStartService.setOnClickListener(this);
  btnBindService.setOnClickListener(this);
  btnUnbindService.setOnClickListener(this);
  btnStopService.setOnClickListener(this);

  intent = new Intent(this, MyService.class);

 }
}


//-------------------------------------------------------------------------------------------------------------
[MyService.xml]
package com.servicetest2;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;

public class MyService extends Service{

 public MyBinder myBinder=new MyBinder();
 
 @Override
 public IBinder onBind(Intent intent) {
  Log.d("MyService","onBind");
  return myBinder;
 }
 
 @Override
 public void onRebind(Intent intent){
  Log.d("MyService","onRebind");
  super.onRebind(intent);
 }
 
 @Override
 public boolean onUnbind(Intent intent){
  Log.d("MyService","onUnbind");
  return super.onUnbind(intent);
 }
 
 @Override
 public void onCreate(){
  Log.d("MyService","onCreate");
  super.onCreate();  
 }
 
 @Override
 public void onDestroy(){
  Log.d("MyService","onDestory");
  super.onDestroy();  
 }

 @Override
 public void onStart(Intent intent, int startId){
  Log.d("MyService","onStart");
  super.onStart(intent, startId);  
 }
 
 public class MyBinder extends Binder{
  MyService getService(){
   return MyService.this;
   
  }
  
 }

}

2012年5月30日 星期三

[Android] [JAVA] 顯示剩餘電量的AP

1). 在主程式中,建立BroadcastReceiver類型的變數,利用BatteryManager讀出電量的資料

2). 註冊receive,僅有此可以利外寫在這,而不用寫在AndroidManifest.xml

//=============================================================
package com.broadcasttest2;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.BatteryManager;
import android.os.Bundle;
import android.widget.TextView;
public class BroadcastTest2 extends Activity {
  private TextView BatteryChange;
  private BroadcastReceiver batteryReceiver = new BroadcastReceiver() {
  @Override
  public void onReceive(Context context, Intent intent) {
    if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
      // 目前電量的值
      int level = intent.getIntExtra("level", 0);
      // 表示電量的總刻度
      int scale = intent.getIntExtra("Scale", 100);
      // 也可以寫成這樣
      //int voltage = intent.getIntExtra(BatteryManager.EXTRA_VOLTAGE, 100);
    BatteryChange.setText("電池用量" + (level * 100 / scale) + "%" );
    }
  }
 };
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);
  BatteryChange = (TextView) findViewById(R.id.battery);
  registerReceiver(batteryReceiver, new IntentFilter(
  Intent.ACTION_BATTERY_CHANGED));
 }
}

[Android] [JAVA] 開機自動執行的AP

1). 寫一個主程式,Broadcast需要去啟動的程式。BroadcastTest1

2). 繼承Broadcast類別,並設定intent連到主程式。StartUpReceiver

3). 在Androidmanifest.xml設置<receive>的標籤

4). 在Androidmanifest.xml添加權限

//=============================================================

[BroadcastTest1]
package com.broadcasttest1;
import android.app.Activity;
import android.os.Bundle;

public class BroadcastTest1 extends Activity {
  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
  }
}


//-------------------------------------------------------------------------------------------------------------

[StartUpReceiver]
package com.broadcasttest1;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class StartUpReceiver extends BroadcastReceiver {
  @Override
  public void onReceive(Context arg0, Intent arg1) {

    Intent intent = new Intent(arg0, BroadcastTest1.class);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    arg0.startActivity(intent);

  }
}


//-------------------------------------------------------------------------------------------------------------

[AndroidManifest.xml]
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="
http://schemas.android.com/apk/res/android"
  package="com.broadcasttest1"
  android:versionCode="1"
  android:versionName="1.0" >

  <uses-sdk android:minSdkVersion="15" />
  
  
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

  <application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name" >

    <!-- Activity -->
    <activity
      android:name=".BroadcastTest1"
      android:label="@string/app_name" >
       <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
       </intent-filter>
    </activity>
       
    <!-- Receiver -->
    <receiver android:name=".StartUpReceiver" >
      <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
      </intent-filter>
    </receiver>
  

  </application>
</manifest>

[Android] [JAVA] Broadcast

1). 編寫一個繼承Broadcast的類別,並實現裡面的onReceive方法

2). 在AndroidManifest.xml使用<receive>標籤指定第一步的類別接收哪一個Broadcast Action

3). 如果有需要,在AndroidManifest.xml添加權限

2012年5月29日 星期二

[Repo] note

● repo的流程:
1). git init -u [site] 會將設定檔及source code的server型態,下載到project_dir/.repo中

2). 若有需要,修改project_dir/.repo/manifest/default.xml
此會決定要下載哪些project,版本分別是什麼

3). 再到project_dir/platform中repo sync
source code就會從server型態轉成git型態,此步不需要網路連線
server型態的存在project_dir/.repo/projects
裡面每一個.git都是一個git project


● git init 若加--mirror,出來的會是git server的型態

2012年5月25日 星期五

[Android] [JAVA] Intent介紹

一、介紹
Intent的功能類似網頁的超連結,使用者可以藉由超連結前往另一個頁面
Intent的動作是從目前的Activity執行另一個Activity。當目前的Activity執行另一個Activity,原來的Activity會進入休眠的狀態,然後將執行的工作權交給另一個Activity



二、intent流程
1). 定義intent
Intent intent=new Intent(動作, 內容)
Intent intent=new Intent(主程式類別.class, 自訂類別.class)
ex: Intent intent = new Intent(DeviceInfo.this, mService.class);

2). 決定誰要去用他
ex: startActivity(Intent)


三、使用intent傳遞資料的流程
1). 使用setClass方法指定執行類別
Intent intent = new Intent(DeviceInfo.this, mService.class);

2). 依照資料型別以Bundle物件打包
Bundle bundle=new Bundle();
bundle.putString("Name","Peter");

3). 利用intent的putExtras方法加入Bundle物件
intent.putExtras(bundle);

4). 使用startActivity方法執行intent
startActivity(intent);



四、取出intent資料的流程
1). 以getIntent()方法取得傳送的Intent
Intent intent=this.getIntent();

2). 利用intent的getExtras()方法,從intent中取得bundle物件
Bundle bundle=intent.getExtras();

3). 根據名稱取得bundle物件的資料
String Name=bundle.getString("Name");

2012年5月24日 星期四

[Example] [Android] [JAVA] Android APP應用2

















按了button觸發啟動Service,顯示Toast並延遲兩秒啟動Notification
按下Notification進入到另外一個Activity
此可以列出device跟sw的資訊

參考文章:


[Android] [JAVA] Service & Notification

按了button觸發啟動Service,顯示Toast並延遲兩秒啟動Notification
按下Notification進入到另外一個Activity

1). 在Activity中設置點擊按鈕觸發的事件如下
宣告Intent所要執行的java檔(mService.java),並啟動Service

2). mService.java檔中宣告Service的lifecycle,分別是onCreate(),onStart(),onDestory
宣告handler,管理新開的thread,名為task的Runnable
宣告Runnable,執行所要做的Notification method

3). 撰寫開啟Notification Manager的method
設定要跳去哪一個Activity
參考[Android] [JAVA] Notification & PendingIntent

4). onCreate()繼承原有的onCreate()
onStart()中寫好延遲2秒去執行task,接著結束此Service,使lifecycle進入onDestory()
onDestory()繼承原有的onDestory()

5). Runnable中去執行Notification的method

//=============================================================


[string.xml]

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <string name="hello">Hello World, DeviceInfo1!</string>
  <string name="app_name">DeviceInfo2</string>
  <string name="android_version">Android Version</string>
  <string name="kernel_version">Kernel Version</string>
  <string name="model_number">Model Number</string>
  <string name="product_sku">Product Sku</string>
  <string name="image_version">Image Version</string>
  <string name="ec_version">EC Version</string>
  <string name="cpu_vendor">CPU Vendor</string>
  <string name="cpu_speed">CPU Speed</string>
  <string name="cpu_version">CPU Version</string>
  <string name="info_submit">Submit</string>
   
  <string name="main_text">Please select the function as list. </string>    
  <string name="main_text_info1">Start service and notification bar after 2 senconds. 
              Then it will change activity to DeviceInfo.</string>    
  <string name="main_submit_info1">1. Device Info</string>     


</resources>


//-------------------------------------------------------------------------------------------------------------


[info.xml]

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:orientation="horizontal" >

  <LinearLayout
    android:layout_width="219dp"
    android:layout_height="691dp"
    android:orientation="vertical" >

  <CheckBox
    android:id="@+id/checkBox1_android_version"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="right"
    android:text="@string/android_version" />

  <CheckBox
    android:id="@+id/checkBox2_kernel_version"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/kernel_version" />

  <CheckBox
    android:id="@+id/checkBox3_model_number"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/model_number" />

  <CheckBox
    android:id="@+id/checkBox4_product_sku"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/product_sku" />

  <CheckBox
    android:id="@+id/checkBox5_image_version"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/image_version" />

  <CheckBox
    android:id="@+id/checkBox6_ec_version"
    android:layout_width="match_parent"
     android:layout_height="wrap_content"
    android:text="@string/ec_version" />

  <CheckBox
    android:id="@+id/checkBox7_cpu_vendor"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/cpu_vendor" />

  <CheckBox
     android:id="@+id/checkBox8_cpu_speed"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/cpu_speed" />

  <CheckBox
     android:id="@+id/checkBox9_cpu_version"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/cpu_version" />

  <Button
    android:id="@+id/submit"
    android:layout_width="191dp"
    android:layout_height="wrap_content"
    android:text="@string/info_submit" />

  <AbsoluteLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
  </AbsoluteLayout>

  </LinearLayout>

  <LinearLayout
    android:layout_width="0dp"
    android:layout_height="match_parent"
    android:layout_weight="1"
    android:orientation="vertical" >

    <TextView
      android:id="@+id/result"
      android:layout_width="1015dp"
      android:layout_height="match_parent"
      android:text="" />

  </LinearLayout>
</LinearLayout>

//-------------------------------------------------------------------------------------------------------------

[main.xml]

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="vertical" >


  <TextView
    android:id="@+id/main_text"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/main_text"
    android:textAppearance="?android:attr/textAppearanceLarge" />


  <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >


  <LinearLayout
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_weight="0.02"
    android:orientation="vertical" >


    <Button
      android:id="@+id/main_submit_info1"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:text="@string/main_submit_info1" />


  </LinearLayout>


  <LinearLayout
    android:layout_width="1028dp"
    android:layout_height="match_parent"
    android:orientation="vertical" >


    <TextView
      android:id="@+id/main_text_info1"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_gravity="bottom"
      android:text="@string/main_text_info1" />


    </LinearLayout>
  </LinearLayout>
</LinearLayout>

//-------------------------------------------------------------------------------------------------------------

[DeviceInfo2.java]

package com.deviceinfo2;


import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;


public class DeviceInfo2 extends Activity {
  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    // 找到元件資源
    TextView text_main=(TextView)findViewById(R.id.main_text);
    TextView text_main_info1=(TextView)findViewById(R.id.main_text_info1);
    Button button_info1 = (Button) findViewById(R.id.main_submit_info1);

    // 設定title字體大小
    text_main.setTextSize(25);
    text_main_info1.setTextSize(20);
    // 設定按鍵觸發的method
    button_info1.setOnClickListener(listDeviceInfo);
}


  private Button.OnClickListener listDeviceInfo = new Button.OnClickListener() {
    @Override
    public void onClick(View v) {

    // Toast
    Toast.makeText(v.getContext(), "Please wait for notification about 2 senconds",
               Toast.LENGTH_LONG).show();
    // 宣告intent,並指定要啟動的class
    Intent intent = new Intent(DeviceInfo2.this, mService.class);
    // 以startservice方式啟動intent
    startService(intent);
    }
  };
}

//-------------------------------------------------------------------------------------------------------------

[mService.java]

package com.deviceinfo2;


import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;


public class mService extends Service {
  private Handler handle = new Handler();
  private int count=0;


  @Override
  public void onCreate() {
    Log.d("TAG", "onCreate");
    super.onCreate();
  }


  @Override
  public IBinder onBind(Intent arg0) {
    return null;
  }


  public void onStart(Intent intent, int startId) {
    Log.d("TAG", "onStart");
    handle.postDelayed(tasks, 2000);
    // 停掉自己這個服務
    mService.this.stopSelf();
  }


  private Runnable tasks = new Runnable() {
    @Override
    public void run() {
    Log.d("TAG", "Runnable");
  Log.d("RUN", "RunCount: " + Integer.toString(count++));
      notification();
      handle.removeCallbacks(tasks);
    }
  };

  private void notification(){
    Log.d("TAG", "Notification");
    // 取得Notification服務
    NotificationManager notificationManager = (NotificationManager) 
              getSystemService(NOTIFICATION_SERVICE);
    // 設定當按下這個通知之後要執行的activity
    Intent notifyIntent = new Intent(mService.this,
                  DeviceInfoActivity.class);
    notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    PendingIntent appIntent = PendingIntent.getActivity(
                  mService.this, 0, notifyIntent, 0);
    Notification notification = new Notification();
    // 設定出現在狀態列的圖示
    notification.icon = R.drawable.ic_launcher;
    // 顯示在狀態列的文字
    notification.tickerText = "notification on status bar.";
    // Notification被點擊後,便消失
    notification.flags |= Notification.FLAG_AUTO_CANCEL;
    // 會有通知預設的鈴聲、振動、light
    notification.defaults |= Notification.DEFAULT_ALL;
    // 設定通知的標題、內容
    notification.setLatestEventInfo(mService.this, "DeviceInfo",
              "Checkoout the infomation of device", appIntent);
    // 送出Notification
    notificationManager.notify(0, notification);
  }


  public void onDestroy() {
    Log.d("TAG", "onDestory");
    super.onDestroy();
  }
}

//-------------------------------------------------------------------------------------------------------------

[DeviceInfoActicity.java]
package com.deviceinfo2;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;

import android.app.Activity;
import android.os.Bundle;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.TextView;
import android.util.Log;
import android.view.View;
import android.os.SystemProperties;

public class DeviceInfoActivity extends Activity {
  private CheckBox checkBox1_android_version, checkBox2_kernel_version,
      checkBox3_model_number, checkBox4_product_sku,
      checkBox5_image_version, checkBox6_ec_version,
      checkBox7_cpu_vendor, checkBox8_cpu_speed, checkBox9_cpu_version;
  private Button button;
  private TextView result;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.info);

    // 取得資源類別中的介面元件
    checkBox1_android_version = (CheckBox) findViewById(R.id.checkBox1_android_version);
    checkBox2_kernel_version = (CheckBox) findViewById(R.id.checkBox2_kernel_version);
    checkBox3_model_number = (CheckBox) findViewById(R.id.checkBox3_model_number);
    checkBox4_product_sku = (CheckBox) findViewById(R.id.checkBox4_product_sku);
    checkBox5_image_version = (CheckBox) findViewById(R.id.checkBox5_image_version);
    checkBox6_ec_version= (CheckBox) findViewById(R.id.checkBox6_ec_version);
    checkBox7_cpu_vendor = (CheckBox) findViewById(R.id.checkBox7_cpu_vendor);
    checkBox8_cpu_speed = (CheckBox) findViewById(R.id.checkBox8_cpu_speed);
    checkBox9_cpu_version = (CheckBox) findViewById(R.id.checkBox9_cpu_version);
    button = (Button) findViewById(R.id.submit);
    result = (TextView) findViewById(R.id.result);

    // button元件要偵聽動作及觸發執行的方法名稱
    button.setOnClickListener(listInfo);
  }

  private Button.OnClickListener listInfo = new Button.OnClickListener() {
    @Override
    public void onClick(View v) {
      result.setText("");
      result.setTextSize(20);

      if (checkBox1_android_version.isChecked()) {
        result.append("Android Version: "
             + SystemProperties.get("ro.build.version.release")
             + "\n\n");
      }
      if (checkBox2_kernel_version.isChecked()) {
        Properties props = System.getProperties();
        result.append("Kernel Version: "
             + props.getProperty("os.version") + "\n\n");
      }
      if (checkBox3_model_number.isChecked()) {
        result.append("Model Number: "
             + SystemProperties.get("ro.product.model") + "\n\n");
      }
      if (checkBox4_product_sku.isChecked()) {
        result.append("Product Sku: "
             + SystemProperties.get("ro.dinfo.sku") + "\n\n");
      }
      if (checkBox5_image_version.isChecked()) {
        result.append("Image Version: "
             + SystemProperties.get("ro.build.display.id") + "\n\n");
      }
      if (checkBox6_ec_version.isChecked()) {
        result.append("EC Version: " + getECVer() + "\n");
      }
      if (checkBox7_cpu_vendor.isChecked()) {
        result.append("CPU Vendor: "
             + SystemProperties.get("ro.cpu.vendor") + "\n\n");
      }
      if (checkBox8_cpu_speed.isChecked()) {
        result.append("CPU Speed: "
             + SystemProperties.get("ro.cpu.speed") + "\n\n");
      }
      if (checkBox9_cpu_version.isChecked()) {
        result.append("CPU Version: "
             + SystemProperties.get("ro.cpu.version") + "\n\n");
      }
    }
  };

  private String getECVer() {
    String str = "";
    int len = 0;
    char[] cbuf = new char[200];
    try {
      FileReader fn = new FileReader("EC路徑");
      try {
        while ((len = fn.read(cbuf, 0, cbuf.length)) >= 0) {
          Log.d("***", str);
          str += String.valueOf(cbuf, 0, len);
        }
      } catch (IOException e) {
        e.printStackTrace();
      }
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    }
    return str;
  }
}

//-------------------------------------------------------------------------------------------------------------

[AndroidManifest.xml]
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.deviceinfo2"
  android:versionCode="1"
  android:versionName="1.0" >

  <uses-sdk android:minSdkVersion="15" />
  <uses-permission android:name="android.permission.VIBRATE"></uses-permission>
  <application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name" >
  <activity
    android:name=".DeviceInfo2"
    android:label="@string/app_name" >
    <intent-filter>
    <action android:name="android.intent.action.MAIN" />

    <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
  </activity>
  <activity android:name="DeviceInfoActivity" >
  </activity>
  <service
    android:name=".mService"
    android:exported="true"
    android:process=":remote" >
  </service>
  </application>
</manifest>