2010年10月27日 星期三

[Android] Build the linux kernel and Android source for the emulator

Build linux kerenl(Eclair):
1.check current kernel version of emulator
$ adb shell
# cat /proc/version
Linux version 2.6.29-00261-g0097074-dirty (digit@digit.mtv.corp.google.com) (gcc version 4.4.0 (GCC) ) #20 Wed Mar 31 09:54:02 PDT 2010
2.download kernel source
$ git clone git://android.git.kernel.org/kernel/common
3.check branch
$ git branch
* android-2.6.27
if it shows * android-2.6.27, list all remote available branches
$ git branch -r
origin/HEAD -> origin/android-2.6.27
origin/android-2.6.25
origin/android-2.6.27
origin/android-2.6.29
origin/android-2.6.32
origin/android-2.6.35
origin/android-2.6.36
origin/android-goldfish-2.6.27
origin/android-goldfish-2.6.29
4.switch branch
$ git checkout --track -b android-goldfish-2.6.29 origin/android-goldfish-2.6.29
5.check branch again
$ git branch
android-2.6.27
* android-goldfish-2.6.29
6.obtain kernel configuration
$ cd /path/to/kernel/common
$ adb pull /proc/config.gz .
$ gunzip config.gz
$ cp config .config
7.building and compiling the kernel
$ ARCH=arm CROSS_COMPILE=/path/to/android/prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin/arm-eabi- make
8.successful message
Kernel: arch/arm/boot/Image is ready
Kernel: arch/arm/boot/zImage is ready


Build Android source:
1.building and compiling Android source
$ PATH=/path/to/android/prebuilt/linux-x86/toolchain/arm-eabi-4.4.0/bin
$ cd /path/to/android/
$ make
2.successful message
Install system fs image: out/target/product/generic/system.img
Target ram disk: out/target/product/generic/ramdisk.img
Target userdata fs image: out/target/product/generic/userdata.img


Start emulator:
$ emulator -kernel /path/to/kernel/common/arch/arm/boot/zImage -show-kernel -verbose -image /path/to/android/out/target/product/generic/system.img -data /path/to/android/out/target/product/generic/userdata.img -ramdisk /path/to/android/out/target/product/generic/ramdisk.img

reference:
* Howto BUILD the LINUX KERNEL for the ANDROID EMULATOR (Eclair version)
* Building Android kernel images
* 編譯android原始碼到模擬器上執行

[Tips] Some problems you may meet when compiling Android

OS: Ubuntu 10.04

編譯Donut:
development/emulator/qtools/trace_reader.cpp: In function 'char* ExtractDexPathFromMmap(const char*)':
development/emulator/qtools/trace_reader.cpp:1012: error: invalid conversion from 'const char*' to 'char*'
development/emulator/qtools/trace_reader.cpp:1015: error: invalid conversion from 'const char*' to 'char*'
make: *** [out/host/linux-x86/obj/EXECUTABLES/bb2sym_intermediates/trace_reader.o] error 1

檢查gcc的版本
$ ls -al /usr/bin/gcc
$ gcc --version

若是為4.4.0以上的版本, 則因為該版本在編譯時的語法要求較高, 導致編譯失敗, 解決方法是降gcc的版本
$ sudo apt-get install gcc-4.3
$ sudo apt-get install g++-4.3
$ sudo ln -f /usr/bin/gcc-4.3 /usr/bin/gcc
$ sudo ln -f /usr/bin/g++-4.3 /usr/bin/g++

也可以透過update-alternatives工具做切換(symbolic links)
安裝各版本的gcc
$ sudo apt-get install gcc-4.1 gcc-4.3 gcc-4.4

使用update-alternatives
Usage: update-alternatives [<option> ...] <command>
Commands:
  --install <link> <name> <path> <priority>
  <link> is the symlink pointing to /etc/alternatives/<name>.
    (e.g. /usr/bin/pager)
  <name> is the master name for this link group.
    (e.g. pager)
  <path> is the location of one of the alternative target files.
    (e.g. /usr/bin/less)
  <priority> is an integer; options with higher numbers have higher priority in
    automatic mode.

建立symbolic links(update-alternatives --install <link> <name> <path> <priority>)
$ sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.1 1
$ sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.3 2
$ sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.4 3

切換gcc版本
$ sudo update-alternatives --config gcc

顯示結果
Selection    Path              Priority   Status
------------------------------------------------------------
  0            /usr/bin/gcc-4.1   1         auto mode
  1            /usr/bin/gcc-4.1   1         manual mode
* 2            /usr/bin/gcc-4.3   2         manual mode
  3            /usr/bin/gcc-4.4   3         manual mode

Press enter to keep the current choice[*], or type selection number: 
reference: [Android開發]Android開發環境建立-gcc的問題


編譯Eclair/Froyo:
Exception in thread "main" java.lang.NoClassDefFoundError: javax/tools/StandardJavaFileManager
at java.lang.ClassLoader.defineClass2(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:719)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:160)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:254)
at java.net.URLClassLoader.access$100(URLClassLoader.java:56)
at java.net.URLClassLoader$1.run(URLClassLoader.java:195)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:268)
at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
at com.sun.tools.javac.main.Main.compile(Main.java:269)
at com.sun.tools.javac.Main.compile(Main.java:87)
at util.build.JavacBuildStep.build(JavacBuildStep.java:69)
at util.build.BuildDalvikSuite.handleTests(BuildDalvikSuite.java:498)
at util.build.BuildDalvikSuite.compose(BuildDalvikSuite.java:170)
at util.build.BuildDalvikSuite.main(BuildDalvikSuite.java:136)
make: *** [out/host/linux-x86/obj/EXECUTABLES/vm-tests_intermediates/tests] Error 1

編輯/etc/security/limits.conf, 註解掉
#* hard nofile 4096
新增
* soft nofile 8192
* hard nofile 8192

target Java: Browser (out/target/common/obj/APPS/Browser_intermediates/classes)
packages/apps/Browser/src/com/android/browser/DownloadTouchIcon.java:81: cannot find symbol
symbol : method getPreferredHttpHost(android.content.Context,java.lang.String)
location: class android.net.Proxy
HttpHost httpHost = Proxy.getPreferredHttpHost(mContext, url);
^
packages/apps/Browser/src/com/android/browser/FetchUrlMimeType.java:73: cannot find symbol
symbol : method getPreferredHttpHost(com.android.browser.BrowserActivity,java.lang.String)
location: class android.net.Proxy
HttpHost httpHost = Proxy.getPreferredHttpHost(mActivity, uri);
^
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
2 errors
make: *** [out/target/common/obj/APPS/Browser_intermediates/classes-full-debug.jar] Error 41
之前提到在Ubuntu使用sun-java-sdk, 若是在java6的環境編譯時就會出現以上問題, 原因大概是@override annotation的關係, 可是JDK 1.6當然有支援annotation, 這部份未來再補充

reference: Android4SAM FAQ

[Tips] 常用到的Android SDK Commands

create sdcard
$ mksdcard [SDCARD_SIZE]M [SDCARD_NAME]

create emulator
$ android create avd --target [TARGET_VER] --name [TARGET_NAME] --sdcard [SDCARD_NAME]

list emulator
$ android list avd

start emulator
$ emulator -avd [TARGET_NAME] -sdcard /path/to/sdcard

install apk via Internet
$ adb export ADBHOST=[MY_ANDROID_IP]
$ /path/to/sdk/tools/adb kill-server
$ adb install [MY_APP.apk]

tcpdump
$ adb shell tcpdump -i any -p -s 0 -w /sdcard/capture.pcap
"-i any": listen on any network interface
"-p": disable promiscuous mode (doesn't work anyway)
"-s 0": capture the entire packet
"-w": write packets to a file (rather than printing to stdout)

2010年10月22日 星期五

[Tips] 在Ubuntu使用sun-java-sdk

/** update @ 2011-09-22 **/
由於jaunty archive已經找不到sun的JDK package,所以現在只能去oracle官網下載:
* jdk-1.5
* jdk-6


一開始在寫Android的應用程式時,都是使用openjdk做為java sdk,
可是總是有說不出的怪,偶爾也會踢到不知名的鐵板,

因此換掉openjdk就是必要的動作啦...

新增repository
// jdk-1.5
$ sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu/ jaunty multiverse"
$ sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu/ jaunty-updates multiverse"

// jdk-1.6
$ sudo add-apt-repository "deb http://archive.canonical.com/ lucid partner"

更新repository內容
$ sudo apt-get update

安裝sun-java-sdk
// jdk-1.5
$ sudo apt-get install sun-java5-jdk sun-java5-plugin

// jdk-1.6
$ sudo apt-get install sun-java6-jdk sun-java6-plugin

更新jre/sdk
// 手動更改
$ update-alternatives --config java
$ update-alternatives --config javac

// 指定更改為jdk-1.6
$ sudo update-java-alternatives -s java-6-sun


那到底是要選擇哪個版本呢? It depends...

比如說在編譯Android source code時,如果使用jdk-1.6的版本,就會遇到以下錯誤訊息,改成jdk-1.5就沒問題了
Checking build tools versions...
********************************************************
You are attempting to build with the incorrect version
of java.

Your version is: java version "1.6.0_22".
The correct version is: 1.5.

Please follow the machine setup instructions at
http://source.android.com/download
********************************************************
build/core/main.mk:117: *** stop. Stop.

但是如果要使用Android的Draw 9-patch工具時,如果使用jdk-1.5的版本,就會遇到以下錯誤訊息,改成jdk-1.6就沒問題了
/usr/share/themes/Ambiance/gtk-2.0/gtkrc:71: Failed to parse property value " GTK_SHADOW_NONE " for `GtkToolbar::shadow-type'
/usr/share/themes/Ambiance/gtk-2.0/gtkrc:72: Failed to parse property value " GTK_SHADOW_NONE " for `GtkMenuBar::shadow-type'
/usr/share/themes/Ambiance/gtk-2.0/gtkrc:75: error: lexical error or unexpected token, expected valid token

reference:
* Oracle Sun JDK vs OpenJDK
* How to install Sun Java 1.5 on Ubuntu 10.04
* JAVA音樂播放器YOYOPlayer1.1發佈

2010年10月20日 星期三

[Tips] Control Your Android Device Remotely Using Mouse and Keyboard

Download: androidscreencast
Launch: $ javaws <jnlp file>

Limitations: slow refresh rate (about 4-5 fps)
Google Code Project here

2010年10月13日 星期三

[Tips] tftp on Ubuntu

大部分產品更新韌體時所用的網路協定是tftp, 簡單/好設定是最大優點, 但也因此有些限制例如不支援加密傳輸等...
在後面講到的啟動參數所指的secure是表示目錄的存取限制罷了

安裝tftpd-hpa(HPA's tftpd)和tftp(tftp client)
server$ sudo apt-get install tftpd-hpa
client$ sudo apt-get install tftp

操作tftpd
server$ sudo /etc/init.d/tftpd-hpa (start|stop|restart)

啟動帶的參數
server$ ps aux|grep tftpd-hpa
/usr/sbin/in.tftpd --listen --user tftp --address 0.0.0.0:69 --secure /var/lib/tftpboot

啟動的設定檔與參數
server$ cat /etc/init/tftpd-hpa.conf /etc/default/tftpd-hpa

使用tftp client下載檔案
client$ tftp my.tftp.server.ip -c get my.file

使用tftp client上傳檔案(在預設路徑)
server$ sudo touch /var/lib/tftpboot/my.file
server$ sudo chmod 755 /var/lib/tftpboot/my.file
client$ tftp my.tftp.server.ip -c put my.file

結論, 不符合我的需求...

TOSSUG讀書會

參加過好幾次TOSSUG的聚會, 要感謝Open Source社群的熱血, 更要感謝pingooo的費心...
昨天是JServ大大的演講, 剛好最近有在看相關的實做, 因此過去瞻仰一下...
這篇只是要紀錄演講內容提到的梗:Google雲端輸入法, 呵呵和道歉真是太神奇了阿!!

2010年10月8日 星期五

[Android] 開機自動啟動的service

程式架構
|-- AndroidManifext.xml     // --> 設定receiver, service, uses-permission
`-- src
    |-- DoService.java      // --> 實際執行的service
    `-- HelloReceiver.java  // --> 接受啟動訊息, 再啟動DoService

直接看扣,
HelloReceiver.java
package hello.receiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class HelloReceiver extends BroadcastReceiver {
  @Override
    public void onReceive(Context context, Intent intent) {
      context.startService(new Intent(context, DoService.class)); 
    }   
}

DoService.java
package hello.receiver;

import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;

public class DoService extends Service {
  private Handler handler = new Handler();
  private int delay_interval = 1000 * 60; // do every 60 seconds

  @Override
    public void onStart(Intent intent, int startId) {
      handler.postDelayed(doUpdate, delay_interval);
      super.onStart(intent, startId);
    }

  public Runnable doUpdate = new Runnable() {
    public void run() {
      handler.postDelayed(this, delay_interval);
    }
  };

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

AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  package="hello.receiver"
  android:versionCode="1"
  android:versionName="1.0">
  <application android:icon="@drawable/icon" android:label="@string/app_name">
    <activity android:name=".HelloReceiver" 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 android:name="HelloReceiver">
      <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
        <category android:name="android.intent.category.HOME" />
      </intent-filter>
    </receiver>
    <service android:name=".myThread">
      <intent-filter>
        <action android:name="hello.receiver.DoService" />
        <category android:name="android.intent.category.DEFAULT" />
      </intent-filter>
    </service>
   </application>
   <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"></uses-permission>
</manifest>

reference:
* Running code on phone boot
* Starting an Android service after boot

2010年10月7日 星期四

[Tips] Couldn't find MySQL manager

目前我也還沒把整個MySQL的運作流程搞清楚, 不過先講情境好了...

OS: Ubuntu 10.04
DB: 5.1.49 (根據[Tips] 常用的LAMP設定檔)

安裝完成後, 原本一切都很美好, 但是在使用了一段時間後(也裝了不少軟體), 某次我想要透過start script啟動(service mysqld start)發現出現這樣的錯誤訊息
Couldn't find MySQL manager (/usr/bin/mysqlmanager) or server (/usr/bin/mysqld_safe)

當下懷疑是被偷裝了第二個MySQL(可能之前閉著眼睛安裝了其他軟體順便又多裝了MySQL), 導致設定檔重複讀取而發生的錯誤, 檢查了一下MySQL的啟動命令/etc/init.d/mysqld原本會讀取/etc/my.cnf, 但不知道為何會讀取到/etc/mysql/my.cnf, 因此才發生以上的錯誤訊息

解決方法就是將設定檔重新指給/etc/my.cnf或是做symbolic link到/etc/mysql/my.cnf