2011年10月27日 星期四

[Android] expired debug certificate

http://developer.android.com/resources/faq/troubleshooting.html#signingcalendar

I can't compile my app because the build tools generated an expired debug certificate

If your development machine uses a locale that has a non-Gregorian calendar, you may encounter problems when first trying to compile and run your application. Specifically, you may find that the Android build tools won't compile your application because the debug key is expired.
The problem occurs because the Keytool utility — included in the JDK and used by the Android build tools — fails to properly handle non-Gregorian locales and may create validity dates that are in the past. That is, it may generate a debug key that is already expired, which results in the compile error.
If you encounter this problem, follow these steps to work around it:
  1. First, delete the debug keystore/key already generated by the Android build tools. Specifically, delete the debug.keystore file. On Linux/Mac OSX, the file is stored in ~/.android. On Windows XP, the file is stored in C:\Documents and Settings\\.android. On Windows Vista, the file is stored in C:\Users\\.android
  2. Next, you can either
    • Temporarily change your development machine's locale (date and time) to one that uses a Gregorian calendar, for example, United States. Once the locale is changed, use the Android build tools to compile and install your app. The build tools will regenerate a new keystore and debug key with valid dates. Once the new debug key is generated, you can reset your development machine to the original locale.
    • Alternatively, if you do not want to change your machine's locale settings, you can generate the keystore/key on any machine using the Gregorian calendar, then copy the debug.keystore file from that computer to the proper location on your development machine.
This problem has been verified on Windows and may apply to other platforms.
For general information about signing Android applications, see Signing Your Applications.

2011年9月28日 星期三

[Android] Dynamically change Options Menu Items in Android

Sometimes, we need to change options menu dynamically, you can follow this example.
	@Override
	public boolean onPrepareOptionsMenu(Menu menu) {
		menu.clear();
		// You can use mEnableMenu to enable meun
		if (mEnableMenu)
		{
			menu.add(0, 0, 0, "Setting");
		}
		return super.onPrepareOptionsMenu(menu);
	}

Reference: 

[Android] How to monitor sdcard mount/unmout?

In this example, we demo the sdcard mount/unmount monitor.
	public void onCreate() {
		super.onCreate();
		this.registerReceiver(this.myReceiver, getSDCardIntentFilter());
	}

	public IntentFilter getSDCardIntentFilter() {
		IntentFilter intentFilter = new IntentFilter();
		intentFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
		intentFilter.addAction(Intent.ACTION_MEDIA_MOUNTED);
		intentFilter.addDataScheme("file");
		return intentFilter;
	}

	private BroadcastReceiver myReceiver = new BroadcastReceiver() {

		@Override
		public void onReceive(Context context, Intent intent) 
		{
			String action = intent.getAction();
			if (action.equals(Intent.ACTION_MEDIA_UNMOUNTED))
			{
			  // handle SD card unmounted
			}
			else if (action.equals(Intent.ACTION_MEDIA_MOUNTED))
			{
			  // handle SD card mounted
			}
		}
	};

[Android] How to block back and search button on Dialog?

It will cancel dialog If user press back or search button on dialog. Therefore, sometimes we need to block back and search button on dialog to ensure the logic of dialog can work normally.
		public void alertDialog(final String title, final String msg, final String btn1, final String btn2, final String btn3, final String cmd, final String data)
		{
			AlertDialog.Builder MyAlertDialog = new AlertDialog.Builder(self);
			MyAlertDialog.setIcon(android.R.drawable.ic_dialog_alert);
			MyAlertDialog.setTitle(title);
			MyAlertDialog.setMessage(msg);
			MyAlertDialog.setCancelable(false); // block back button

			MyAlertDialog.setOnKeyListener(new DialogInterface.OnKeyListener()
			{
				@Override
				public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event)
				{
					if (keyCode==KeyEvent.KEYCODE_SEARCH)	// block search button
						return true;
					else
						return false;
				}
			});

			DialogInterface.OnClickListener OkClick = new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface dialog, int which) {
				// Handle onClick
				}
			};
			if (btn1 != null)
				MyAlertDialog.setPositiveButton(btn1, OkClick );
			if (btn2 != null)
				MyAlertDialog.setNegativeButton(btn2, OkClick );
			if (btn3 != null)
				MyAlertDialog.setNeutralButton(btn3, OkClick );

			 MyAlertDialog.show();
		}

[Android] How to create status bar notification?

To create a status bar notification:


1. Get a reference to the NotificationManager:
String ns = Context.NOTIFICATION_SERVICE;
NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns);

2. Instantiate the Notification:
int icon = R.drawable.notification_icon;
CharSequence tickerText = "Hello";
long when = System.currentTimeMillis();

Notification notification = new Notification(icon, tickerText, when);

3. Define the Notification's expanded message and Intent:
Context context = getApplicationContext();
CharSequence contentTitle = "My notification";
CharSequence contentText = "Hello World!";
Intent notificationIntent = new Intent(this, MyClass.class);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);

4. Pass the Notification to the NotificationManager:
private static final int HELLO_ID = 1;

mNotificationManager.notify(HELLO_ID, notification);
That's it. Your user has now been notified.

Reference:

2011年9月16日 星期五

[Android] How can I refresh MediaStore on Android?

Sometimes, we cannot get the correct information from MediaStore after file add or delete. We need to do MediaStore refresh to make MediaStore parsing the information instantly.
package com.roryok.MediaRescan;

import android.app.Activity;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;

public class MediaRescan extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, 
                Uri.parse("file://" + Environment.getExternalStorageDirectory()))); 
        setContentView(R.layout.main);
    }

    //Rescan the sdcard after copy the file
    private void rescanSdcard() throws Exception{     
      Intent scanIntent = new Intent(Intent.ACTION_MEDIA_MOUNTED, 
                Uri.parse("file://" + Environment.getExternalStorageDirectory()));   
      IntentFilter intentFilter = new IntentFilter(Intent.ACTION_MEDIA_SCANNER_STARTED);
      intentFilter.addDataScheme("file");     
      sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, 
                Uri.parse("file://" + Environment.getExternalStorageDirectory())));    
    }
}


Reference:

2011年9月2日 星期五

[JavaScript] How to format string?

String.format = function(src){
  if (arguments.length == 0) 
    return null;

  var args = Array.prototype.slice.call(arguments, 1);
  return src.replace(/\{(\d+)\}/g, function(m, i)
  {
    return args[i];
  });
};

Demo:
msg will be "This is variable A and variable B.

var template = "This is variable {0} and variable {1}";
var variable1 = "A";
var variable2 = "B";
var msg = String.format(template, variable1, variable2);

[Java] How to check if a directory is not empty?

This is a example to demo how to check if a directory is not empty?

package org.kodejava.example.io;

import java.io.File;

public class EmptyDirCheck {
    public static void main(String[] args) {
        File file = new File("/home/username/data");

        //
        // Check to see if the object represent a directory.
        //
        if (file.isDirectory()) {
            //
            // Get list of file in the directory. When its length is not zero
            // the folder is not empty.
            //
            String[] files = file.list();

            if (files.length > 0) {
                System.out.println("The " + file.getPath() + " is not empty!");
            }
        }
    }
}

Reference:

2011年8月31日 星期三

[JavaScript] How to auto truncate text?

Sometimes we need to auto truncate text when the width of text division is not enough to fit the text. For example, we have a text like "Hello, I am a long long long text." But the text division only can show "Hello, I am a long long". I this case, the last long could not be shown normal. To ensure text presentation normally in screen, we need a function to calculate the width of input text and auto truncate text with tail token (ex: ...).

JavaScript code:
function autoEllipseText(element, text, width)
{
   element.innerHTML = '' + text + '';
   inSpan = document.getElementById('ellipsisSpan');
   if(inSpan.offsetWidth > width)
   {
      var i = 1;
      inSpan.innerHTML = '';
      while(inSpan.offsetWidth < (width) && i < text.length)
      {
         inSpan.innerHTML = text.substr(0,i) + '...';
         i++; 
      } 
                
      returnText = inSpan.innerHTML; 
      element.innerHTML = '';
      return returnText;
   }
   return text;
}

Usage:
function setCellText()
{
   cellElement = document.getElementById('textCell');
   textBoxElement = document.getElementById('cellText');
   cellElement.innerHTML = 
       autoEllipseText(cellElement, textBoxElement.value, 80);
}

References:

2011年6月2日 星期四

[Java] function如何傳不定參數

private void MyParameterizedFunction(String param1, int param2, Boolean... params) {
    assert params.length <= 1;
    boolean param3 = params.length > 0 ? params[0].booleanValue() : false;
}
 
private void test()
{
    MyParameterizedFunction("", 1);
}

Reference:

2011年5月27日 星期五

[Chrome] How To Print Preview in Google Chrome

How To Print Preview in Google Chrome

  1. First of all you would need to download an extension called IE Tab. This is a very useful extension which opens websites in Google Chrome as if its opening in Internet Explorer. You can get more details on it here.
  2. Now open the page which you want to print (or print preview), and click on the IE Tab extension icon besides your address bar. It would open a new tab which would display the page as if its Internet Explorer.
  3. Once the page loads, right click anywhere on the page and you can see the option ‘Print Preview’ in the context menu.
  4. Click on it and that’s it, you would be able to preview how the print would look.

    References:

    2011年5月19日 星期四

    [Android] How to set hostname on Android device?

    $ su
    # setprop net.hostname whateveryouwant
    

    Please restart wifi after set hostname.

    You can use the following code to check if it works.
    InetAddress addr = InetAddress.getByName("192.168.15.105"); // 192.168.15.105 is your device ip
    
    Reference:

    2011年5月17日 星期二

    [Android] tcpdump for Android devices

    tcpdump for Android devices

    • tcpdump, a powerful command-line packet analyzer.
    How to install on your device?
    Unzip tcpdump.rar
    // copy to tcpdump to your /system/bin:
    1. adb remount 
    2. adb push tcpdump /system/bin
    3. adb shell chmod 777 /system/bin/tcpdump 
    

    How to run tcpdump on your device?
    Run: adb shell tcpdump -i any -w /storage/netlog.cap
    Stop: USE Ctrl + C to abort this packet monitor. 
    Download log: adb pull /storage/netlog.cap c:\ 
    Delete log: adb rm /storage/netlog.cap 

    tcpdump parameters
    -i :後面接要監聽的網路介面,例如 eth0, lo, ppp0 等等的介面;any表示所有的網路介面
    -w :後面接要監聽所得的封包資料儲存的檔名
    
    

    References

    2011年5月5日 星期四

    [Android] SharedPreferences - a simple example

    我們可以用Android的SharedPreferences來讀寫裝置上的偏好設定檔。

    首先需要使用getSharedPreferences(String, int)來取得SharedPreferences。
    • 第一個參數是偏好設定檔的名稱,如果指定的設定檔名稱不存在的話,當使用者使用SharedPreferences.edit()而且Editor.commit()去更新資料時該偏好設定檔會自動產生。
    • 第二個參數是偏好設定檔的模式,0或MODE_PRIVATE是預設的參數,MODE_WORLD_READABLE 和MODE_WORLD_WRITEABLE為設定控制權限,MODE_MULTI_PROCESS為多個程序可以共用的偏好設定檔。

    String PREFS_FILENAME = "APP_SETTING";
    SharedPreferences mConfig = getSharedPreferences(PREFS_FILENAME, 0);
    SharedPreferences.Editor mConfigEditor = mConfig.edit();
    
    mConfigEditor.putBoolean("Setting1", true);        // set Setting2 = true
    mConfigEditor.commit();                  // We do commit to save data
    boolean bSetting1 = mConfig.getBoolean("Setting1", false);// get Setting1 from SharedPreferences
    System.out.println("Vince bSetting1 = " + bSetting1);   // bSetting = true
    
    mConfigEditor.putBoolean("Setting2", true);        // set Setting2 = true
    boolean bSetting2 = mConfig.getBoolean("Setting2", false);// get Setting2 from SharedPreferences
    System.out.println("Vince bSetting2 = " + bSetting2);   // bSetting = false
    
    

    References:

    [Eclipse] JAR Library: Export and Import

    Step by Step:
    1. In project source code, Right Click Mouse Button.
    2. Select [Export]
    3. Select Java > JAR file.
    4. Check the source code that you want to export as JAR library.
    5. Select the export destination.
    6. Press [Next].
    7. Press [Next].
    8. Press [Finish].

    Reference:

    [Java] 用YourKit看Java程式的CPU & Memory

    YourKit
    Step 1: Select monitor application
    • Launch your eclipse and YourKit.
    • Run your code.
    • Your will see your eclipse and running process on YourKit.

    Step 2: Capture Memory Snapshot
    • Click Capture Memory Snapshot to see memory usage in detail.
    • Launch your eclipse and YourKit.


    Step 3: Memory Statistics
    • You will see memory statistics.
    • For example, if you want to see who use char[], we can click "Click to start calculation"

    Step 4: Do Memory Calculation
    • You can see who use this object (ex: char[]).

    Step 5: Object Explore
    • You can use "Object Explore" to see data in memory.


    Step 6: Paths of GC roots
    • In Memory Statistics, right click class (ex: char[])
    • Click "Paths of GC roots", you can see the GC status of this object.
    References

    2011年4月29日 星期五

    [Eclipse] Eclipse快速鍵整理

    快速鍵
    • F11: Debug
    • Ctrl + F11: Run.
    • Ctrl + Shift + B: Toggle Breakpointer.
    • Ctrl + Shift + F: Format.
    • Ctrl + Mouse left click: View Source Code.
    • Ctrl + /: Add Comment.

    延伸閱讀

    [Java] What is an interface in Java

    Java Interface:
    1. 由於Java沒有Class多重繼承,為了讓物件具有多種型態,可以用Interface(介面)的達到多重繼承的需求。
    2. 介面方法宣告預設都是"public",有沒有加public預設仍是public。
    3. 介面宣告預設都是abstract,有沒有加abstract預設仍是abstract。
    4. 當定義類別時,可以使用"implements"關鍵字來指定要實作哪個介面,介面中所有定義的方法都要實作。
    5. 由於介面中的方法預設都是public,所以實作介面的類別中,方法必須宣告為public,否則無法通過編譯。
    


    public interface IRequest {
      public abstract void execute(); // 可以用 void execute(); 省略public或abstract,其意義相同。
    } 
    

    public class HelloRequest implements IRequest {
      private String name;
      public HelloRequest(String name) 
      {
        this.name = name;
      }
    
      public void execute() {
        System.out.printf("Hello! %s!%n", name);
      }
    } 
    

    實作多個介面的方式: 
    
    public class 類別名稱 implements 介面1, 介面2, 介面3 { 
        // 介面實作 
    }
    

    介面進行繼承的方式: 
    
    public interface 名稱 extends 介面1, 介面2 { 
        // ... 
    } 
    


    References:

    2011年4月27日 星期三

    [Android] Build NDK Environment

    NDK是什麼?
    The Android NDK is a toolset that lets you embed components that make use of native code in your Android applications.

    安裝NDK

    Step 1:安裝Cygwin
    • 下載點:到http://cygwin.com/install.html下載setup.exe
    • Cygwin Setup: Next
    • Cygwin Setup - Choose Installation Type: Install from Internet > Next
    • Cygwin Setup - Choose Installation Directory: All Users > Next
    • Cygwin Setup - Select Local Package Directory > Next
    • Cygwin Setup - Select Connection Type: Direct Connection > Next
    • Cygwin Setup - Choose Download Site(s): ftp:/ftp.ntu.edu.tw > Next
    • Cygwin Setup - Select Packages as below > Next


    • Launch Cygwin and run sure "gcc -v" and "make -v" to verify if it works correctly.
    $ gcc -v
    Reading specs from /usr/lib/gcc/i686-pc-cygwin/3.4.4/specs
    Configured with: /managed/gcc-build/final-v3-bootstrap/gcc-3.4.4-999/configure --verbose --program-suffix=-3 --prefix=/usr --exec-prefix=/us
    r --sysconfdir=/etc --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --enable-languages=c,ada,c++,d
    ,f77,pascal,java,objc --enable-nls --without-included-gettext --enable-version-specific-runtime-libs --without-x --enable-libgcj --disable-j
    ava-awt --with-system-zlib --enable-interpreter --disable-libgcj-debug --enable-threads=posix --enable-java-gc=boehm --disable-win32-registr
    y --enable-sjlj-exceptions --enable-hash-synchronization --enable-libstdcxx-debug
    Thread model: posix
    gcc version 3.4.4 (cygming special, gdc 0.12, using dmd 0.125)
    
    $ make -v
    GNU Make 3.81
    Copyright (C) 2006  Free Software Foundation, Inc.
    This is free software; see the source for copying conditions.
    There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
    PARTICULAR PURPOSE.
    
    This program built for i686-pc-cygwin
    

    Step 2:安裝NDK

    • 下載點:到http://developer.android.com/sdk/ndk/index.html 下載Android NDK for Windows
    • Cygwin Setup: Next
    • Cygwin Setup - Choose Installation Type: Install from Internet > Next
    • Cygwin Setup - Choose Installation Directory: All Users > Next
    • Cygwin Setup - Select Local Package Directory > Next
    • Cygwin Setup - Select Connection Type: Direct Connection > Next
    • Cygwin Setup - Choose Download Site(s): ftp:/ftp.ntu.edu.tw > Next
    • Cygwin Setup - Select Packages as below > Next
    • 然後到C:\cygwin\home\"使用者名稱" 目錄下,用windows編輯器編輯.bash_profile :
    在最後一行後加入下面四行,然後存檔:
    PATH=/android-ndk-r5:${PATH}
    NDK_ROOT=/android-ndk-r5
    NDK_Sample=/android-ndk-r5/samples
    export PATH NDK_ROOT NDK_Sample
    (NDK_Sample是指定你的JNI程式所要放置的目錄,這邊我我指定到/android-ndk-r5/samples,這個參數會在Eclipse的C編譯中使用到。)
    
    • 開啟Cygwin Bash Shell到/android-ndk-r5/samples/hello-jni/目錄下,執行ndk-build
    vince_huang@VinceH-DT ~
    $ cd /android-ndk-r5/samples/hello-jni/
    
    vince_huang@VinceH-DT /android-ndk-r5/samples/hello-jni
    $ ndk-build
    Gdbserver      : [arm-linux-androideabi-4.4.3] libs/armeabi/gdbserver
    Gdbsetup       : libs/armeabi/gdb.setup
    Install        : libhello-jni.so => libs/armeabi/libhello-jni.so
    

    Step 2:安裝Eclipse CDT(C/C++ Development Tool)

    • Eclipse Help > Install New Software... > Add...
    • Name: CDT
    • Location: http://download.eclipse.org/tools/cdt/releases/galileo
    • 安裝Eclipse C/C++ Development Tools
    • 安裝CDT GNU Toolchain Build Support
    • 安裝CDT GNU Toolchain Debug Support
    • 安裝CDT Utilities
    • 安裝Eclipse C/C++ Development Platform
    • 安裝完成後,Eclipse會要求重新開啟Eclipse,重開Eclipse後便可以在Eclipse中編輯C/C++程式。

    相關連結

    [Android] MediaStore

    The Media provider contains meta data for all available media on both internal and external storage devices.

    A Example:

    String[] projection = new String[] {
      Images.ImageColumns._ID,
      Images.ImageColumns.BUCKET_DISPLAY_NAME,
      Images.ImageColumns.BUCKET_ID,
      Images.ImageColumns.DATE_TAKEN,
      Images.ImageColumns.DESCRIPTION,
      Images.ImageColumns.IS_PRIVATE,
      Images.ImageColumns.LATITUDE,
      Images.ImageColumns.LONGITUDE,
      Images.ImageColumns.MINI_THUMB_MAGIC,
      Images.ImageColumns.ORIENTATION,
      Images.ImageColumns.PICASA_ID,
      Images.ImageColumns.DATA,
      Images.ImageColumns.DATE_ADDED,
      Images.ImageColumns.DATE_MODIFIED,
      Images.ImageColumns.DISPLAY_NAME,
      Images.ImageColumns.MIME_TYPE,
      Images.ImageColumns.SIZE,
      Images.ImageColumns.TITLE
    };
    
    // We can use the following query method to query data.
    //Cursor cursor = managedQuery(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection, null, null, null);
    
    Cursor cursor = getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection, null, null, null);
    
    int count = cursor.getCount();
    
    System.out.println("count = " + count);
    
    for (int i=0; i<count; i++)
    {
      cursor.moveToPosition(i);
      int columnSize = cursor.getColumnCount();
      for (int j=0; j<columnsize; j++)
      {
        System.out.println("index = " + j + " " + cursor.getColumnName(j) + " = " + cursor.getString(j));
      }
    }

    Reference:

    2011年4月25日 星期一

    [JavaScript] JSLint 文斯不負責報導

    JSLint是一套可以幫你檢查你的JavaScript程式中語法和語意是否有錯誤的工具。

    接下來我們來看看JSLint能幫我們什麼忙?

    全域變數(Global Variables)
    JavaScript 中只要變數使用前沒有先用var宣告過,該變數就會是全域變數。這可能會導致變數名字拼錯等問題發生。JSLint會檢查是否所有變數和函數在它被使用前應該要先宣告過。 這可以使程式更容易閱讀。

    分號(Semicolon)
    JavaScript類似C語言的語法,因此需要使用分號來分隔的程式陳述(Statement)。在JavaScript中,可以換行空格,也可以作為一個分號做為程式陳述的結尾,但這可能會導致錯誤發生。因此JSLint會檢查每個程式陳述之後 , 除了for、function、if、switch、try和while。 JSLint 不希望看到不必要的分號或空語句。

    逗號(Comma)逗號運算元可以用於程式技巧表達上。它也可能掩蓋一些程式錯誤。JSLint會檢查是否逗號只作為分隔符號,且不能作為運算元(除在程式初始化和for的程式陳述上)。它不希望看到省略元素在陣列字元上。也不應該有額外的逗號。一個逗號不應該出現在陣列或物件的最後一個元素後,因為它在某些瀏覽器上會出錯。

    程式範圍(Scope)
    在許多程式語言中,程式區塊定義了程式的範圍。 在程式區塊中定義的變數在程式區塊外則是不可見的。在JavaScript中,程式區塊則不會定義了程式的範圍。只有函數才有程式範圍的概念。如果一個變數在函數中任何地方被定義的,則該變數在函數中任何地方皆為可用的。因此JavaScript的程式區塊易造成混淆。JSLint會檢查是否程式區塊只在function、if、switch、while、for、do和try中。在程式區塊的範圍中,通常變數的量定義是在第一次使用時。但由於JavaScript沒有程式範圍的概念,因此最好在函數開始就宣告所有的變數,且最好一行只宣告一個變數。

    程式區塊(Block)
    JSLint會檢查是否只有if、while、do和for的程式陳述有程式區塊。

    表達式陳述(Expression Statements)
    1. For in: 使用for in陳述可以列舉變數中所有的元素,但確保不會存取到不想存取的屬性,最好在for in中用hasOwnProperty來檢查一下。
    2. switch: 在下一個case或default之前的陳述必須是break、return或throw。
    3. var: 每一個變數或函數皆需要使用var宣告,且只能宣告一次,但參數(parameters)、引數(arguments)及程式區塊則不用。
    4. with: 不要使用with,它容易造成混淆。
    5. =: 邏輯判斷時不要使用=。
    6. == and !=: 與null、0、undefined、true、false這些值比較時,一定要用===和!==,因為 JavaScript 有神祕的型別轉換,讓你的 null==undefined 但是null != false,要判斷是否是以上列舉值的其中任一種時,就用===和!==吧,如果只是要 true/false 判斷,則可以用==和!=。
    7. labels: 只能在break有作用的程式區塊(ex: switch, while, do, and for)允許使用label。
    8. Unreachable Code: return、break、continue或throw陳述後必須接著}、case或 default。以避免產生執行不到的程式碼。
    9. Confusing Pluses and Minuses: 不要使用+後接+或++,-後接-或--的情形。
    10. ++ and --: 不要使用++或--。
    11. Bitwise Operators: 不要使用bit運算元。
    12. eval is evil: 不要使用eval。
    13. void: 在JavaScript中void代表undefined,因此不要使用void。
    14. Regular Expressions: 正規表示法之前的字元需為(、=、:或,。
    15. Constructors and new: 不要使用new在Number、String或Boolean上,也不要使用new在物件(Object)或陣列(Array)上。可以使用 {} 建立物件, [] 建立陣列。
    16. Unsafe Characters: \u0000-\u001f、\u007f-\u009f、\u00ad、\u0600-\u0604、\u070f、\u17b4、\u17b5、\u200c-\u200f、\u2028-\u202f、\u2060-\u206f、\ufeff、\ufff0-\uffff為不安全字元,使用時需使用脫離(Escape)函數處理。

    References:

    2011年4月22日 星期五

    [Java] ThreadPoolExecutor

    一個任務通過execute(Runnable)方法被加入到執行緒池,任務就是一個Runnable類型的物件,任務的執行方法就是Runnable類型物件的run()方法。

    當一個任務通過execute(Runnable)方法欲加入到執行緒池時:

    • 如果此時執行緒池中的數量小於corePoolSize,即使執行緒池中的執行緒都處於空閒狀態,也要新增新的執行緒來處理被加入的任務。
    • 如果此時執行緒池中的數量等於 corePoolSize,但是緩衝佇列 workQueue未滿,那麼任務被放入緩衝佇列。
    • 如果此時執行緒池中的數量大於corePoolSize,緩衝佇列workQueue滿,並且執行緒池中的數量小於maximumPoolSize,建新的執行緒來處理被添加的任務。
    • 如果此時執行緒池中的數量大於corePoolSize,緩衝佇列workQueue滿,並且執行緒池中的數量等於maximumPoolSize,那麼通過 handler所指定的策略來處理此任務。

    也就是說處理任務的優先順序為:
    • 核心執行緒corePoolSize、任務佇列workQueue、最大執行緒maximumPoolSize,如果三者都滿了,使用handler處理被拒絕的任務。
    • 當執行緒池中的執行緒數量大於 corePoolSize時,如果某執行緒閒置時間超過keepAliveTime,執行緒將被終止。這樣,執行緒池可以動態的調整池中的執行緒數。
    unit可選的參數為java.util.concurrent.TimeUnit中的幾個靜態屬性:
    • NANOSECONDS
    • MICROSECONDS
    • MILLISECONDS
    • SECONDS。

    workQueue常用的是:
    • java.util.concurrent.ArrayBlockingQueue

    handler有四個選擇:
    • ThreadPoolExecutor.AbortPolicy():丟出java.util.concurrent.RejectedExecutionException異常
    • ThreadPoolExecutor.CallerRunsPolicy():重試加入當前的任務,他會自動重複調用execute()方法
    • ThreadPoolExecutor.DiscardOldestPolicy():放棄最舊的任務
    • ThreadPoolExecutor.DiscardPolicy():放棄當前的任務

    Constructor: Creates a new ThreadPoolExecutor with the given initial parameters and default thread factory and handler.
    
    ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue)


    核心執行緒池大小(corePoolSize)
    • 池中所保存的執行緒數,包括空閒執行緒。
    最大執行緒池大小(maximumPoolSize)
    • maximumPoolSize - 池中允許的最大執行緒數。
    工作存活時間(KeepAliveTime)
    • keepAliveTime - 當執行緒數大於核心時,此為終止前多餘的空閒執行緒等待新任務的最長時間。
    工作存活時間(unit)
    • unit - keepAliveTime 參數的時間單位。
    工作佇列(workQueue)
    • workQueue - 執行前用於保持任務的佇列。此佇列僅保持由 execute 方法提交的 Runnable 任務。
    import java.util.concurrent.*;
    import java.util.*;
     
    class MyThreadPoolExecutor
    {
        int poolSize = 2;
     
        int maxPoolSize = 2;
     
        long keepAliveTime = 10;
     
        ThreadPoolExecutor threadPool = null;
     
        final ArrayBlockingQueue queue = new ArrayBlockingQueue(
                5);
     
        public MyThreadPoolExecutor()
        {
            threadPool = new ThreadPoolExecutor(poolSize, maxPoolSize,
                    keepAliveTime, TimeUnit.SECONDS, queue);
     
        }
     
        public void runTask(Runnable task)
        {
            // System.out.println("Task count.."+threadPool.getTaskCount() );
            // System.out.println("Queue Size before assigning the
            // task.."+queue.size() );
            threadPool.execute(task);
            // System.out.println("Queue Size after assigning the
            // task.."+queue.size() );
            // System.out.println("Pool Size after assigning the
            // task.."+threadPool.getActiveCount() );
            // System.out.println("Task count.."+threadPool.getTaskCount() );
            System.out.println("Task count.." + queue.size());
     
        }
     
        public void shutDown()
        {
            threadPool.shutdown();
        }
     
        public static void main(String args[])
        {
            MyThreadPoolExecutor mtpe = new MyThreadPoolExecutor();
            // start first one
            mtpe.runTask(new Runnable()
            {
                public void run()
                {
                    for (int i = 0; i < 10; i++)
                    {
                        try
                        {
                            System.out.println("First Task");
                            Thread.sleep(1000);
                        } catch (InterruptedException ie)
                        {
                        }
                    }
                }
            });
            // start second one
            /*
             * try{ Thread.sleep(500); }catch(InterruptedException
             * ie){}
             */
            mtpe.runTask(new Runnable()
            {
                public void run()
                {
                    for (int i = 0; i < 10; i++)
                    {
                        try
                        {
                            System.out.println("Second Task");
                            Thread.sleep(1000);
                        } catch (InterruptedException ie)
                        {
                        }
                    }
                }
            });
            // start third one
            /*
             * try{ Thread.sleep(500); }catch(InterruptedException
             * ie){}
             */
            mtpe.runTask(new Runnable()
            {
                public void run()
                {
                    for (int i = 0; i < 10; i++)
                    {
                        try
                        {
                            System.out.println("Third Task");
                            Thread.sleep(1000);
                        } catch (InterruptedException ie)
                        {
                        }
                    }
                }
            });
            // start fourth one
            /*
             * try{ Thread.sleep(500); }catch(InterruptedException
             * ie){}
             */
            mtpe.runTask(new Runnable()
            {
                public void run()
                {
                    for (int i = 0; i < 10; i++)
                    {
                        try
                        {
                            System.out.println("Fourth Task");
                            Thread.sleep(1000);
                        } catch (InterruptedException ie)
                        {
                        }
                    }
                }
            });
            // start fifth one
            /*
             * try{ Thread.sleep(500); }catch(InterruptedException
             * ie){}
             */
            mtpe.runTask(new Runnable()
            {
                public void run()
                {
                    for (int i = 0; i < 10; i++)
                    {
                        try
                        {
                            System.out.println("Fifth Task");
                            Thread.sleep(1000);
                        } catch (InterruptedException ie)
                        {
                        }
                    }
                }
            });
            // start Sixth one
            /*
             * try{ Thread.sleep(500); }catch(InterruptedException
             * ie){}
             */
            mtpe.runTask(new Runnable()
            {
                public void run()
                {
                    for (int i = 0; i < 10; i++)
                    {
                        try
                        {
                            System.out.println("Sixth Task");
                            Thread.sleep(1000);
                        } catch (InterruptedException ie)
                        {
                        }
                    }
                }
            });
            mtpe.shutDown();
        }
     
    }
    
    Reference:

    2011年3月9日 星期三

    [Android] Basic tips for Android protection

    Vince筆記
    • Afirewall- aFirewall is the free version of Android Firewall which blocks incoming calls from numbers you specify. If you don’t wants to receive a particular call from a person then install this superb application. This application works fantastically and is a must have for anyone who wants to block incoming calls from telemarketers, bill collectors or your run of the mill harassing calls.
      • 延伸閱讀
        • Reference 1
    • Droidhunter- it is a security service for Android with inbuilt anti-virus, interruption detection, online managing service and incoming alerts. This app is similar to the traditional desktop security software except that it looks for Android specific threats. Android phone scans as “Very Clean” but user reviews report the interception of suspicious apps as well as other Android security threats. This program comes in a free version as well as a paid version which can be used to locate a lost or stolen phone.
      • 延伸閱讀
        • Reference 1
    • App protector- it is an application which allows you to lock your choice of applications on your Android phone. You can set a password, and when you try to enter a protected app, you will be asked to enter the password. Useful if your phone is stolen or if you store information on your phone you’d rather not have accessed by people you let look at your Android phone. Protect as many or as few applications as you like and remove the password lock on applications at anytime. One thing to keep in mind is you will want to protect your uninstaller application, so a person can’t simply uninstall this program to remove the password locks and then access your sensitive information. This program comes in a free time-limited trial (7 days). You can remove the password anytime, but a person can’t simply remove the password locks by uninstalling the application.
      • 延伸閱讀
        • Reference 1

    相關連結





        2011年3月8日 星期二

        [Android] Logcat in Java

        在Eclipse中叫出LogCat的小視窗
        Window -> Show View -> Other,找Android -> LogCat

        Log基本用法
        Log.v(TAG, Message): 詳細訊息(Verbose)
        Log.d(TAG, Message): 除錯訊息(Debug)
        Log.i(TAG, Message): 資訊訊息(INFO)
        Log.w(TAG, Message): 警告訊息(Warning)
        Log.e(TAG, Message): 錯誤訊息(Error)
        
        第一個欄位是TAG,第二個欄位是Message,TAG可以方便做filter
        Ex: Log.i("Tag", "This log.i for logcat");
        

        如何filter
        1. 在Eclipse中叫出LogCat的小視窗
        2. 按下綠色加號產生filter






        3. 設定filter

        [Android] Android Service

        什麼是Android Service
        • A service can run in the background to perform work even while the user is in a different application.
        • A service can allow other components to bind to it, in order to interact with it and perform interprocess communication.
        • A service runs in the main thread of the application that hosts it, by default.

        來個例子

        在AndroidManifest.xml中增加一個Service,其中ExampleService為你Service class的名稱
        <manifest ... >
          ...  
          <application ... >      
          <service android:name=".ExampleService" />
          ...  
         </application>
        </manifest>

        建立myService.java,參考自Android學習筆記 - 背景執行服務(Service)
        package com.cyberlink.dtcpip; 
        import android.app.Service; 
        import android.content.Intent; 
        import android.os.Handler; 
        import android.os.IBinder; 
        import android.util.Log; 
        import java.util.Date; 
        
        //繼承android.app.Service 
        public class myService extends Service { 
            private Handler handler = new Handler(); 
          
            @Override
            public IBinder onBind(Intent intent) { 
                return null; 
            } 
          
            @Override
            // The old onStart method that will be called on the pre-2.0
            // platform. On 2.0 or later we override onStartCommand().
            public int onStartCommand(Intent intent, int flags, int startId) { 
            // We want this service to continue running until it is explicitly
            // stopped, so return sticky.
                handler.postDelayed(showTime, 1000); 
                super.onStartCommand(intent, flags, startId);
                return START_STICKY;
            } 
          
            @Override
            public void onDestroy() { 
                handler.removeCallbacks(showTime); 
                super.onDestroy(); 
            } 
              
            private Runnable showTime = new Runnable() { 
                public void run() { 
                    //log目前時間 
                    Log.i("[MyService]", "Time = " + new Date().toString()); 
                    handler.postDelayed(this, 1000); 
                } 
            }; 
        }
        

        By returning the START_STICKY constant when your Service is started, you tell Android that if it has to kill the Service to free up valuable resources, then you’d like it to restart the Service when resource become available again.

        啟動Service
        Intent intent = new Intent(this, myService.class); 
        startService(intent); 
        

        關閉Service
        Intent intent = new Intent(this, myService.class); 
        stopService(intent); 
        

        相關連結

        2011年3月7日 星期一

        [MultiMedia] FLV format

        The FLV header
        All FLV files begin with the following header:
        • Signature(UI8): Signature byte always 'F' (0x46)
        • Signature(UI8): Signature byte always 'L' (0x4C)
        • Signature(UI8): Signature byte always 'V' (0x56)
        • Version(UI8): File version (for example, 0x01 for FLV version 1)
        • TypeFlagsReserved(UB[5]): Must be 0
        • TypeFlagsAudio(UB[1]): Audio tags are present
        • TypeFlagsReserved(UB[1]): Must be 0
        • TypeFlagsVideo(UB[1]): Video tags are present
        • DataOffset(UI32): Offset in bytes from start of file to start of body (that is, size of header)
        The DataOffset field usually has a value of 9 for FLV version 1. This field is present to
        accommodate larger headers in future versions.

        Example:
        0x46 0x4C 0x56 0x01 0x05 0x00 0x00 0x00 0x09
        means
        TypeFlagsAudio = 1
        TypeFlagsVideo = 1
        DataOffset = 0x00 0x00 0x00 0x09
        

        The FLV file body
        After the FLV header, the remainder of an FLV file consists of alternating back-pointers and tags. They interleave as shown in the following table:
        • PreviousTagSize0(UI32): Always 0
        • Tag1(FLVTAG): First tag
        • PreviousTagSize1(UI32): Size of previous tag, including its header. For FLV version 1, this value is 11 plus the DataSize of the previous tag.
        • Tag2(FLVTAG): Second tag
        • ...
        • PreviousTagSizeN-1(UI32): Size of second-to-last tag
        • TagN(FLVTAG): Last tag
        • PreviousTagSizeN(UI32): Size of last tag
        FLV tags
        FLV tags have the following format:
        • TagType(UI8): Type of this tag. Values are: 0x8: audio, 0x9: video, 0x12: script data and all others: reserved.
        • DataSize(UI24): Length of the data in the Data field
        • Timestamp(UI24): Time in milliseconds at which the data in this tag applies. This value is relative to the first tag in the FLV file, which always has a timestamp of 0.
        • TimestampExtended(UI8): Extension of the Timestamp field to form a SI32 value. This field represents the upper 8 bits, while the previous Timestamp field represents the lower 24 bits of the time in milliseconds.
        • StreamID(UI24): Always 0.
        • Data: If TagType == 0x08 for AUDIODATA; If TagType == 0x09 for VIDEODATA; If TagType == 0x12 for SCRIPTDATAOBJECT

        Example:
        0x12 0x00 0x03 0x15 0x00 0x00 0x00 0x00 0x00 0x00 0x00
        means
        Tagype = 0x12
        DataSize = 0x00 0x03 0x15
        TimeStamp = 0x00 0x00 0x00
        TimeStampExtend = 0x00
        StreamID = 0x00 0x00 0x00

        [Java] JLint 文斯不負責報導

        今天要介紹的是這套JLint(http://artho.com/jlint/)的工具

        簡單來說,JLint是一個可以幫你分析你寫的Java程式碼的工具,包括語法(syntax)及語義(semantic)檢查,不一致性及同步問題等。其中AntiC.exe是負責語法檢查,JLint.exe是負責語義檢查。

        快速入門(如果你只想知道如何用
        • 下載:到JLint官方網站下載(http://artho.com/jlint/download.shtml),我是下載Windows版 jlint-2.3.zip
        • 解壓縮:將jlint-2.3.zip解壓縮。如果你只是要使用JLint來檢查Java程式碼,你需要用到 jlint-2.3\jlintwin32\中的兩個執行檔(antic.exe和jlint.exe)就可以了。
        • 語法檢查:antic.exe src\*.java(ex: src為放java檔的folder),執行完antic.exe就可以看到結果輸出。
        • 語義檢查:jlint.exe src\*.java(ex: src為放java檔的folder),執行完jlint.exe就可以看到結果輸出。
        細部講解(如果你想知道更詳細功能
        • AntiC能檢查的是
          • 字裡行間的蟲蟲戰爭(Bugs in tokens)
            • 跳離符號後數字必須是八進位數字。
            • 跳離符號後數字個數必須小於三個字元。
            • Unicode的跳離符號\u後接的是十六進位數字。
            • 跳離符號接了錯誤的字元(非八進位字元或Unicode)。
            •  少用Trigraph sequence(以??為前置字元的三字元序列)為妙。
            • 多字元的字元定義(char ch = 'ab';)是不一定可移植的。
            • 長整數定義時後置字元最好是大寫的L,小寫l會跟數字1混淆。
          • 運算子間的恩怨情仇(Operator priorities)
            • 運算子運算時最好有括號表示優先順序。
            • AND運算子優先權比OR運算子高。
            • 位元位移運算子優先權較低。
            • 邏輯中的等於是==而不是=。 
            • 指定運算子=具較低優先權。
            • 位元運算子具較低優先權。
          • 程式主體的誰是誰非(Statement body)
            • 迴圈中的程式碼最好用括號定義範圍。 
            • 邏輯IF的程式碼最好用括號定義範圍。
            • 邏輯ELSE的程式碼最好用括號定義範圍。
            • 條件邏輯SWITCH的程式碼最好用括號定義範圍。
            • 條件邏輯中的CASE或DEFAULT的程式碼最好用括號定義範圍。
            • 條件邏輯中的CASE或DEFAULT的程式碼不要忘了BREAK。

        • JLint能檢查的是
          • 同步(synchronization)
            • 死結(deadlock)
            • 競賽情況(Race Condition)
          • 繼承(inheritance)
            • 派生類別的方法名稱沒有正確覆蓋有相同名稱的基本類別的方法名稱
            • 派生類別中的元件名稱與基本類別元件名稱相同
            • 區域變數名稱與元件中全域變數名稱相同
            • 方法的finalize()未能Call到super.finalize()
          • 資料流程(data flow)
            • method的參數傳遞可能有null的情形
            • 變數的使用可能會有null的情形
            • 運算元可能會有null的情形,會有method的使用問題
            • 零個運算元的運算
            • 運算結果都為零
            • 位元位移計算超過位數(例如:int y >>= 32, 最最最最多只能shift 31位)
            • 位元位移計算超過範圍(例如:int x >>= 32 - (y & 31); // range of count is [1,32])
            • 變數值的轉換超出範圍(例如:int x = 100000; short s = x;)
            • 變數值的轉換會導致資料遺失(例如:數值範圍較大的變數轉換到數值範圍較小的變數)
            • 變數運算後的型態轉換會導致資料遺失(例如:兩個整數相乘)
            • 邏輯判斷恆為真(True)或假(False)
            • 只有當比較的運算元都為0時,邏輯判斷才會成立邏輯判斷邏輯判斷恆為真 邏輯判斷恆為真邏輯判斷恆為真 邏輯判斷恆為真邏輯判斷恆為真邏輯判斷恆為真邏輯判斷恆為真 最最最邏
            • 餘數運算恆等於第一個運算元
            • char與short比較
            • 字串比對誤用物件比對
            • 不等式的比較可以用等式的比較 替代
            • Switch中Case的值超出範圍




      • 更詳細地說明請看http://artho.com/jlint/manual.html
      • 2011年3月4日 星期五

        [Android] Android Debug Bridge (ADB)

        http://developer.android.com/guide/developing/tools/adb.html

        You can find the adb tool in <sdk>/platform-tools/.

        Installing an Application
        adb install 
        

        Copying Files to or from an Emulator/Device Instance
        To copy a file or directory (recursively) from the emulator or device, use
        adb pull <remote>> <local>

        To copy a file or directory (recursively) from the emulator or device, use
        adb push <local> <remote>

        2011年3月3日 星期四

        [Android] undefined reference to in ndk-build

        在ndk-build時, 需要的static library都有定義到

        LOCAL_STATIC_LIBRARIES := libABC \
        LOCAL_STATIC_LIBRARIES += libCDE \
        

        但卻還是發生undefined reference to `xxxxxx' 時

        這時候可能是 static library 的順序不對, 改一下順序再試看看吧
        LOCAL_STATIC_LIBRARIES := libCDE \
        LOCAL_STATIC_LIBRARIES += libABC \
        

        [HTTP] what is Chunk?

        http://developers.sun.com/mobility/midp/questions/chunking/

        The problem surfaces when a server tries to read a chunked request it isn't prepared for. In the body of a chunked message, each chunk of data begins with the size of the chunk and an extra CR/LF:

        C\r\n
        Some data...
        11\r\n
        Some more data...
        0\r\n
        

        [Android] System process cannot write file to the /sdcard

        http://groups.google.com/group/android-platform/browse_thread/thread/065bc037e44af858

        The system process is explicitly forbidden to open files on SD because those devices are frequently removable during runtime.

        If a process holds open file descriptors when the file system is unmounted, that process will be killed by the kernel.

        In the case of the system process, that would bring down the whole Android runtime; hence the restriction.

        Applications resident on SD complicate this a bit, but that's the basic problem in a nutshell, and is the reason for the explicit policy that you're seeing in action.

        For your test suite, you might consider using a two-process architecture in which the system-process test code communicates via the Binder or other IPC mechanism with another process whose job is mostly to handle the file I/O.

        Note that system process can write file to the /data.

        [Android] logcat in JNI

        http://blog.xuite.net/xoanonlin/LoveFor/39052853

        1. 加入header檔

        #include <android log.h>
        

        2. 加入需要的定義
        #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG  , "liblog",__VA_ARGS__) 
        
        #define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, "liblog",__VA_ARGS__)
        
        #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, "liblog",__VA_ARGS__)
        
        #define LOGW(...) __android_log_print(ANDROID_LOG_WARN, "liblog",__VA_ARGS__)
        
        #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, "liblog",__VA_ARGS__)
        

        3. 用法
        LOGD("Debug Message is from JNI");
        

        4. 加入LOCAL_LDLIBS在Android.mk, 這行要在include $(BUILD_SHARED_LIBRARY)之前, 否則會有undefined reference的錯誤
        LOCAL_LDLIBS :=  -L$(SYSROOT)/usr/lib -llog
        

        2011年3月2日 星期三

        [Android] wildcard usage in Android.mk

        For example, you can use wildcard to enumerate *.c in the folder.

        MY_NativeC_FILES += $(wildcard $(LOCAL_PATH)/*.c)
        

        [Android] Preprocessor definition in NDK

        http://stackoverflow.com/questions/4022180/how-to-add-a-custom-macro-when-using-ndk

        If you would like to add a special definition when compiling your NDK code (jni) add the following into your Android.mk:

        LOCAL_CFLAGS:=-DMYDEFINE
        

        This will define the Macro MYDEFINE in your c/c++ code. Here an example

        #ifdef MYDEFINE
        // We build the project with this special macro
        #else
        // We build without setting the macro in the LOCAL_CFLAGS
        #endif
        

        [Android] Android.mk Documentation

        http://hashspeaks.wordpress.com/2010/01/27/android-mk-documentation/

        Android.mk file syntax specification
        
        Introduction:
        -------------
        
        This document describes the syntax of Android.mk build file
        written to describe your C and C++ source files to the Android
        NDK. To understand what follows, it is assumed that you have
        read the docs/OVERVIEW.TXT file that explains their role and
        usage.
        
        Overview:
        ---------
        
        An Android.mk file is written to describe your sources to the
        build system. More specifically:
        
        - The file is really a tiny GNU Makefile fragment that will be
          parsed one or more times by the build system. As such, you
          should try to minimize the variables you declare there and
          do not assume that anything is not defined during parsing.
        
        - The file syntax is designed to allow you to group your
          sources into 'modules'. A module is one of the following:
        
            - a static library
            - a shared library
        
          Only shared libraries will be installed/copied to your
          application package. Static libraries can be used to generate
          shared libraries though.
        
          You can define one or more modules in each Android.mk file,
          and you can use the same source file in several modules.
        
        - The build system handles many details for you. For example, you
          don't need to list header files or explicit dependencies between
          generated files in your Android.mk. The NDK build system will
          compute these automatically for you.
        
          This also means that, when updating to newer releases of the NDK,
          you should be able to benefit from new toolchain/platform support
          without having to touch your Android.mk files.
        
        Note that the syntax is *very* close to the one used in Android.mk files
        distributed with the full open-source Android platform sources. While
        the build system implementation that uses them is different, this is
        an intentional design decision made to allow reuse of 'external' libraries'
        source code easier for application developers.
        
        Simple example:
        ---------------
        
        Before describing the syntax in details, let's consider the simple
        "hello JNI" example, i.e. the files under:
        
            apps/hello-jni/project
        
        Here, we can see:
        
          - The 'src' directory containing the Java sources for the
            sample Android project.
        
          - The 'jni' directory containing the native source for
            the sample, i.e. 'jni/hello-jni.c'
        
            This source file implements a simple shared library that
            implements a native method that returns a string to the
            VM application.
        
          - The 'jni/Android.mk' file that describes the shared library
            to the NDK build system. Its content is:
        
           ---------- cut here ------------------
           LOCAL_PATH := $(call my-dir)
        
           include $(CLEAR_VARS)
        
           LOCAL_MODULE    := hello-jni
           LOCAL_SRC_FILES := hello-jni.c
        
           include $(BUILD_SHARED_LIBRARY)
           ---------- cut here ------------------
        
        Now, let's explain these lines:
        
          LOCAL_PATH := $(call my-dir)
        
        An Android.mk file must begin with the definition of the LOCAL_PATH variable.
        It is used to locate source files in the development tree. In this example,
        the macro function 'my-dir', provided by the build system, is used to return
        the path of the current directory (i.e. the directory containing the
        Android.mk file itself).
        
          include $(CLEAR_VARS)
        
        The CLEAR_VARS variable is provided by the build system and points to a
        special GNU Makefile that will clear many LOCAL_XXX variables for you
        (e.g. LOCAL_MODULE, LOCAL_SRC_FILES, LOCAL_STATIC_LIBRARIES, etc...),
        with the exception of LOCAL_PATH. This is needed because all build
        control files are parsed in a single GNU Make execution context where
        all variables are global.
        
          LOCAL_MODULE := hello-jni
        
        The LOCAL_MODULE variable must be defined to identify each module you
        describe in your Android.mk. The name must be *unique* and not contain
        any spaces. Note that the build system will automatically add proper
        prefix and suffix to the corresponding generated file. In other words,
        a shared library module named 'foo' will generate 'libfoo.so'.
        
        IMPORTANT NOTE:
        If you name your module 'libfoo', the build system will not
        add another 'lib' prefix and will generate libfoo.so as well.
        This is to support Android.mk files that originate from the
        Android platform sources, would you need to use these.
        
          LOCAL_SRC_FILES := hello-jni.c
        
        The LOCAL_SRC_FILES variables must contain a list of C and/or C++ source
        files that will be built and assembled into a module. Note that you should
        not list header and included files here, because the build system will
        compute dependencies automatically for you; just list the source files
        that will be passed directly to a compiler, and you should be good.
        
        Note that the default extension for C++ source files is '.cpp'. It is
        however possible to specify a different one by defining the variable
        LOCAL_DEFAULT_CPP_EXTENSION. Don't forget the initial dot (i.e. '.cxx'
        will work, but not 'cxx').
        
          include $(BUILD_SHARED_LIBRARY)
        
        The BUILD_SHARED_LIBRARY is a variable provided by the build system that
        points to a GNU Makefile script that is in charge of collecting all the
        information you defined in LOCAL_XXX variables since the latest
        'include $(CLEAR_VARS)' and determine what to build, and how to do it
        exactly. There is also BUILD_STATIC_LIBRARY to generate a static library.
        
        There are more complex examples under apps/, with commented
        Android.mk files that you can look at.
        
        Reference:
        ----------
        
        This is the list of variables you should either rely on or define in
        an Android.mk. You can define other variables for your own usage, but
        the NDK build system reserves the following variable names:
        
        - names that begin with LOCAL_  (e.g. LOCAL_MODULE)
        - names that begin with PRIVATE_, NDK_ or APP_  (used internally)
        - lower-case names (used internally, e.g. 'my-dir')
        
        If you need to define your own convenience variables in an Android.mk
        file, we recommend using the MY_ prefix, for a trivial example:
        
           ---------- cut here ------------------
            MY_SOURCES := foo.c
            ifneq ($(MY_CONFIG_BAR),)
              MY_SOURCES += bar.c
            endif
        
            LOCAL_SRC_FILES += $(MY_SOURCES)
           ---------- cut here ------------------
        
        So, here we go:
        
        NDK-provided variables:
        - - - - - - - - - - - -
        
        These GNU Make variables are defined by the build system before
        your Android.mk file is parsed. Note that under certain circumstances
        the NDK might parse your Android.mk several times, each with different
        definition for some of these variables.
        
        CLEAR_VARS
            Points to a build script that undefines nearly all LOCAL_XXX variables
            listed in the "Module-description" section below. You must include
            the script before starting a new module, e.g.:
        
              include $(CLEAR_VARS)
        
        BUILD_SHARED_LIBRARY
            Points to a build script that collects all the information about the
            module you provided in LOCAL_XXX variables and determines how to build
            a target shared library from the sources you listed. Note that you
            must have LOCAL_MODULE and LOCAL_SRC_FILES defined, at a minimum before
            including this file. Example usage:
        
              include $(BUILD_SHARED_LIBRARY)
        
            note that this will generate a file named lib$(LOCAL_MODULE).so
        
        BUILD_STATIC_LIBRARY
            A variant of BUILD_SHARED_LIBRARY that is used to build a target static
            library instead. Static libraries are not copied into your
            project/packages but can be used to build shared libraries (see
            LOCAL_STATIC_LIBRARIES and LOCAL_STATIC_WHOLE_LIBRARIES described below).
            Example usage:
        
              include $(BUILD_STATIC_LIBRARY)
        
            Note that this will generate a file named lib$(LOCAL_MODULE).a
        
        TARGET_ARCH
            Name of the target CPU architecture as it is specified by the
            full Android open-source build. This is 'arm' for any ARM-compatible
            build, independent of the CPU architecture revision.
        
        TARGET_PLATFORM
            Name of the target Android platform when this Android.mk is parsed.
            For now, only 'android-3' is supported, which corresponds to the
            Android 1.5 platform.
        
        TARGET_ARCH_ABI
            Name of the target CPU+ABI when this Android.mk is parsed.
            For now, only 'arm' is supported, which really means the following:
        
               ARMv5TE or higher CPU, with 'softfloat' floating point support
        
            Other target ABIs will be introduced in future releases of the NDK
            and will have a different name. Note that all ARM-based ABIs will
            have 'TARGET_ARCH' defined to 'arm', but may have different
            'TARGET_ARCH_ABI'
        
        TARGET_ABI
            The concatenation of target platform and abi, it really is defined
            as $(TARGET_PLATFORM)-$(TARGET_ARCH_ABI) and is useful when you want
            to test against a specific target system image for a real device.
        
            By default, this will be 'android-3-arm'
        
        NDK-provided function macros:
        - - - - - - - - - - - - - - -
        
        The following are GNU Make 'function' macros, and must be evaluated
        by using '$(call <function>)'. They return textual information.
        
        my-dir
            Returns the path of the current Android.mk's directory, relative
            to the top of the NDK build system. This is useful to define
            LOCAL_PATH at the start of your Android.mk as with:
        
                LOCAL_PATH := $(call my-dir)
        
        all-subdir-makefiles
            Returns a list of Android.mk located in all sub-directories of
            the current 'my-dir' path. For example, consider the following
            hierarchy:
        
                sources/foo/Android.mk
                sources/foo/lib1/Android.mk
                sources/foo/lib2/Android.mk
        
            If sources/foo/Android.mk contains the single line:
        
                include $(call all-subdir-makefiles)
        
            Then it will include automatically sources/foo/lib1/Android.mk and
            sources/foo/lib2/Android.mk
        
            This function can be used to provide deep-nested source directory
            hierarchies to the build system. Note that by default, the NDK
            will only look for files in sources/*/Android.mk
        
        this-makefile
            Returns the path of the current Makefile (i.e. where the function
            is called).
        
        parent-makefile
            Returns the path of the parent Makefile in the inclusion tree,
            i.e. the path of the Makefile that included the current one.
        
        grand-parent-makefile
            Guess what...
        
        Module-description variables:
        - - - - - - - - - - - - - - -
        
        The following variables are used to describe your module to the build
        system. You should define some of them between an 'include $(CLEAR_VARS)'
        and an 'include $(BUILD_XXXXX)'. As written previously, $(CLEAR_VARS) is
        a script that will undefine/clear all of these variables, unless explicitely
        noted in their description.
        
        LOCAL_PATH
            This variable is used to give the path of the current file.
            You MUST define it at the start of your Android.mk, which can
            be done with:
        
              LOCAL_PATH := $(call my-dir)
        
            This variable is *not* cleared by $(CLEAR_VARS) so only one
            definition per Android.mk is needed (in case you define several
            modules in a single file).
        
        LOCAL_MODULE
            This is the name of your module. It must be unique among all
            module names, and shall not contain any space. You MUST define
            it before including any $(BUILD_XXXX) script.
        
            The module name determines the name of generated files, e.g.
            lib<foo>.so for a shared library module named <foo>. However
            you should only refer to other modules with their 'normal'
            name (e.g. <foo>) in your NDK build files (either Android.mk
            or Application.mk)
        
        LOCAL_SRC_FILES
            This is a list of source files that will be built for your module.
            Only list the files that will be passed to a compiler, since the
            build system automatically computes dependencies for you.
        
            Note that source files names are all relative to LOCAL_PATH and
            you can use path components, e.g.:
        
              LOCAL_SRC_FILES := foo.c \
                                 toto/bar.c
        
            NOTE: Always use Unix-style forward slashes (/) in build files.
                  Windows-style back-slashes will not be handled properly.
        
        LOCAL_CPP_EXTENSION
            This is an optional variable that can be defined to indicate
            the file extension of C++ source files. The default is '.cpp'
            but you can change it. For example:
        
                LOCAL_CPP_EXTENSION := .cxx
        
        LOCAL_C_INCLUDES
            An optional list of paths, relative to the NDK *root* directory,
            which will be appended to the include search path when compiling
            all sources (C, C++ and Assembly). For example:
        
                LOCAL_C_INCLUDES := sources/foo
        
            Or even:
        
                LOCAL_C_INCLUDES := $(LOCAL_PATH)/../foo
        
            These are placed before any corresponding inclusion flag in
            LOCAL_CFLAGS / LOCAL_CPPFLAGS
        
        LOCAL_CFLAGS
            An optional set of compiler flags that will be passed when building
            C *and* C++ source files.
        
            This can be useful to specify additionnal macro definitions or
            compile options.
        
            IMPORTANT: Try not to change the optimization/debugging level in
                       your Android.mk, this can be handled automatically for
                       you by specifying the appropriate information in
                       your Application.mk, and will let the NDK generate
                       useful data files used during debugging.
        
            NOTE: In android-ndk-1.5_r1, the corresponding flags only applied
                  to C source files, not C++ ones. This has been corrected to
                  match the full Android build system behaviour. (You can use
                  LOCAL_CPPFLAGS to specify flags for C++ sources only now).
        
        LOCAL_CXXFLAGS
            An alias for LOCAL_CPPFLAGS. Note that use of this flag is obsolete
            as it may disappear in future releases of the NDK.
        
        LOCAL_CPPFLAGS
            An optional set of compiler flags that will be passed when building
            C++ source files *only*. They will appear after the LOCAL_CFLAGS
            on the compiler's command-line.
        
            NOTE: In android-ndk-1.5_r1, the corresponding flags applied to
                  both C and C++ sources. This has been corrected to match the
                  full Android build system. (You can use LOCAL_CFLAGS to specify
                  flags for both C and C++ sources now).
        
        LOCAL_STATIC_LIBRARIES
            The list of static libraries modules (built with BUILD_STATIC_LIBRARY)
            that should be linked to this module. This only makes sense in
            shared library modules. 
        
        LOCAL_SHARED_LIBRARIES
            The list of shared libraries *modules* this module depends on at runtime.
            This is necessary at link time and to embed the corresponding information
            in the generated file.
        
            Note that this does not append the listed modules to the build graph,
            i.e. you should still add them to your application's required modules
            in your Application.mk
        
        LOCAL_LDLIBS
            The list of additional linker flags to be used when building your
            module. This is useful to pass the name of specific system libraries
            with the "-l" prefix. For example, the following will tell the linker
            to generate a module that links to /system/lib/libz.so at load time:
        
              LOCAL_LDLIBS := -lz
        
            See docs/STABLE-APIS.TXT for the list of exposed system libraries you
            can linked against with this NDK release.
        
        LOCAL_ALLOW_UNDEFINED_SYMBOLS
            By default, any undefined reference encountered when trying to build
            a shared library will result in an "undefined symbol" error. This is a
            great help to catch bugs in your source code.
        
            However, if for some reason you need to disable this check, set this
            variable to 'true'. Note that the corresponding shared library may fail
            to load at runtime.
        
        LOCAL_ARM_MODE
            By default, ARM target binaries will be generated in 'thumb' mode, where
            each instruction are 16-bit wide. You can define this variable to 'arm'
            if you want to force the generation of the module's object files in
            'arm' (32-bit instructions) mode. E.g.:
        
              LOCAL_ARM_MODE := arm
        
            Note that you can also instruct the build system to only build specific
            sources in arm mode by appending an '.arm' suffix to its source file
            name. For example, with:
        
               LOCAL_SRC_FILES := foo.c bar.c.arm
        
            Tells the build system to always compile 'bar.c' in arm mode, and to
            build foo.c according to the value of LOCAL_ARM_MODE.
        
            NOTE: Setting APP_OPTIM to 'debug' in your Application.mk will also force
                  the generation of ARM binaries as well. This is due to bugs in the
                  toolchain debugger that don't deal too well with thumb code.

        [Android] LOCAL_LDFLAGS in Android.mk

        可以用LOCAL_LDFLAGS讀入static library

        LOCAL_LDFLAGS += \
        libABC.a \
        libDEF.a
        

        2011年2月25日 星期五

        [Android] File Operations in Android NDK

        FILE* file = fopen("/sdcard/hello.txt","w+");
        
        if (file != NULL)
        {
        
            fputs("HELLO WORLD!\n", file);
            fflush(file);
            fclose(file);
        }
        

        Dont forget to place a permission for it. in the Android manifest place a

        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE">;
        

        http://stackoverflow.com/questions/1992953/file-operations-in-android-ndk

        2011年1月31日 星期一

        [MultiMedia] How to Build the Filter Graph

        Building the Filter Graph
        1. Filter Graph Manager
          • CLSID_FilterGraph: Creates the Filter Graph Manager on a shared worker thread. (通常都用CLSID_FilterGraph)
          • CLSID_FilterGraphNoThread: Creates the Filter Graph Manager on the application thread. 
        2. IGraphBuilder Interface
          • Connect: Connects two pins. If they will not connect directly, this method connects them with intervening transforms.
          • Render: Adds a chain of filters to a specified output pin to render it. (將Source的output pin 試著connect到已Add的filter)
          • RenderFile: Builds a filter graph that renders the specified file. (也就是AutoRender)
          • AddSourceFilter: Adds a source filter to the filter graph for a specific file. 
        3. IMediaControl Interface
          • Run: Runs all the filters in the filter graph.
          • Pause: Pauses all filters in the filter graph.
          • Stop: Stops all the filters in the filter graph.
          • StopWhenReady: Pauses the filter graph, allowing filters to queue data, and then stops the filter graph.
          • GetState: Retrieves the state of the filter graph. 
        4. IMediaEventEx Interface
          • SetNotifyWindow: Registers a window to process event notifications.
          • SetNotifyFlags: Enables or disables event notifications.
          • GetNotifyFlags: Determines whether event notifications are enabled. 
          Reference

          [MultiMedia] What's New for DirectShow in Windows 7 - Filters

          Microsoft MPEG-1/DD/AAC Audio Decoder


          This filter decodes the following audio formats:
          • MPEG-1 audio layers I and II.
          • Backward-compatible MPEG-2 audio, layers I and II (ISO/IEC 13818-3), mono and stereo only.
          • Advanced Audio Coding (AAC) Low Complexity (LC) profile.
          • High-Efficiency AAC (HE-AAC) version 1 and version 2.
          • Pass-through Digital Theater Systems (DTS) for digital output.
          • LPCM, mono and stereo only, with or without PES headers.
          • Dolby Digital.
          • Dolby Digital Plus, including conversion from Dolby Digital Plus to Dolby Digital for digital output.
          Note This filter is not supported on IA-64-based platforms.

          In the registry, the friendly name of this filter is "Microsoft DTV-DVD Audio Decoder".

          Microsoft MPEG-2 Video Decoder


          • This filter decodes MPEG-1, MPEG-2, H.264 video.
          • Note Decoding of H.264 video requires Windows 7.
          Note This filter is not supported on IA-64-based platforms.

          In the registry, the friendly name of this filter is "Microsoft DTV-DVD Video Decoder".

          [MultiMedia] DirectShow Note

          This is a studying note for DirectShow. It summarizes some key knowledge of DirectShow and a studying roadmap. Current progress is Building the Filter Graph (2010/03/08).

          DirectShow
          • The Microsoft DirectShow application programming interface (API) is a media-streaming architecture for the Microsoft Windows platform.
          • DirectShow simplifies media playback, format conversion, and capture tasks.
          • DirectShow is based on the Component Object Model (COM).
          • DXVA: DirectX Video Acceleration.
          • EVR: Enhanced Video Renderer.
          • VMR: Video Mixing Renderer.
          • DMOs: Microsoft DirectX Media Objects.
          Filters and Filter Graphs


          The building block of DirectShow is a software component called a filter. A filter is a software component that performs some operation on a multimedia stream. For example, DirectShow filters can
          • read files
          • get video from a video capture device
          • decode various stream formats, such as MPEG-1 video
          • pass data to the graphics or sound card
          Filters receive input and produce output.

          In DirectShow, an application performs any task by connecting chains of filters together, so that the output from one filter becomes the input for another. A set of connected filters is called a filter graph.

          How To Play a File

          See example and sample code on MSDN.

          The DirectShow Solution

          See DirectShow component relationship diagram on MSDN.

          About DirectShow Filters

          The connection points are also COM objects, called pins. Filters use pins to move data from one filter the next. In DirectShow, a set of filters is called a filter graph.

          Filters have three possible states: running, stopped, and paused. When a filter is running, it processes media data. When it is stopped, it stops processing data. The paused state is used to cue data before running.

          The primary function of most filters is to process and deliver media data. How that occurs depends on the type of filter:
          • A push source has a worker thread that continuously fills samples with data and delivers them downstream.
          • A pull source waits for its downstream neighbor to request a sample. It responds by writing data into a sample and delivering the sample to the downstream filter. The downstream filter creates the thread that drives the data flow.
          • A transform filter has samples delivered to it by its upstream neighbor. When it receives a sample, it processes the data and delivers it downstream.
          • A renderer filter receives samples from upstream, and schedules them for rendering based on the time stamps.
          About the Filter Graph Manager

          The Filter Graph Manager is a COM object that controls the filters in a filter graph. It performs many functions, including the following:
          • State changes: Coordinating state changes among the filters.
          • Reference clock: Establishing a reference clock.
          • Graph events: Communicating events back to the application.
          • Graph-building methods: Providing methods for applications to build the filter graph.
          About Media Types
           
          The media type is a universal and extensible way to describe digital media formats. When two filters connect, they agree on a media type. The media type identifies what kind of data the upstream filter will deliver to the downstream filter, and the physical layout of the data. If two filters cannot agree on a media type, they will not connect.
           
          Media types are defined using the AM_MEDIA_TYPE structure. This structure contains the following information:

          • Major type: The major type is a GUID that defines the overall category of the data. Major types include video, audio, unparsed byte stream, MIDI data, and so forth.

          • Subtype: The subtype is another GUID, which further defines the format. For example, within the video major type, there are subtypes for RGB-24, RGB-32, UYVY, and so forth. Within audio, there is PCM audio, MPEG-1 payload, and others. The subtype provides more information than the major type, but it does not define everything about the format. For example, video subtypes do not define the image size or the frame rate. These are defined by the format block, described below.

          • Format block: The format block is a block of data that describes the format in detail. The format block is allocated separately from the AM_MEDIA_TYPE structure. The pbFormat member of the AM_MEDIA_TYPE structure points to the format block. The pbFormat member is typed void* because the layout of the format block changes depending on the media type. For example, PCM audio uses a WAVEFORMATEX structure. Video uses various structures, including VIDEOINFOHEADER and VIDEOINFOHEADER2. The formattype member of the AM_MEDIA_TYPE structure is a GUID that specifies which structure is contained in the format block. Each format structure is assigned a GUID. The cbFormat member specifies the size of the format block. Always check these values before dereferencing the pbFormat pointer.
          About Media Samples and Allocators

          Filters deliver data across pin connections. Data moves from the output pin of one filter to the input pin of another filter. The most common way for the output pin to deliver the data is by calling the IMemInputPin::Receive method on the input, although a few other mechanisms exist as well. More detail see MSDN.

          How Hardware Devices Participate in the Filter Graph

          Wrapper Filters


          All DirectShow filters are user mode software components. In order for a kernel mode hardware device, such as a video capture card, to join a DirectShow filter graph, the device must be represented as a user-mode filter. This function is performed by specialized "wrapper" filters provided with DirectShow. DirectShow also provides a filter called KsProxy, which can represent any type of Windows Driver Model (WDM) streaming device. Hardware vendors can extend KsProxy to support custom functionality, by providing a Ksproxy plug-in, which is a COM object aggregated by KsProxy.

          The wrapper filters expose COM interfaces that represent the capabilities of the device. The application uses these interfaces to pass information to and from the filter. The filter translates the COM method calls into device driver calls, passes that information to the driver in kernel mode, and then translates the result back to the application. Some filters support custom driver properties through the IKsPropertySet interface.

          For application developers, wrapper filters enable the application to control devices just as they control any other DirectShow filter. No special programming is required; the details of communicating with the kernel-mode device are encapsulated within the filter.




          References

          [MultiMedia] Mpeg Format

          Mpeg Format
          • Mpeg TS: Transport Stream. 
          • Mpeg PS: Program Stream.
          Mpeg TS Format
          • MPEG_TS_HD_NA: 192 bytes with 4 bytes zero time code.
          • MPEG_TS_HD_NA_ISO: 188 bytes without time code.
          • MPEG_TS_HD_NA_T: 192 bytes with 4 bytes valid time code.
          • MPEG_TS_JP_T: 192 bytes with 4 bytes valid time code. Has a CP Header.
          MPEG_TS_JP_T CP Header Structure
          • 14 bytes header begin with 0x00 (byte_length is 10~13 bytes)
          • 4 bytes time code
          • 188 bytes payload begin with 0x47
          MPEG_TSJP_T CP Header Structure Example
          • First CP Header begin at 00 00 00 00: 00 00 00 00 00 00 00 00 00 00 [00 0F FF C0] => Byte Length = 00 0F FF C0 means the length of the first segment (Time Code (4) + Payload (188)) is 00 0F FF C0
          • Time Code (4 bytes): BE 84 0A DC
          • Payload (188 bytes): 47 40 00 11 00 00 B0 11 40 F2 C1 00 00 00 00 E0 ...
          • Second CP Header begin at 00 0F FF CD: First CP Header Size + Byte Length = 14 + 00 0F FF C0 = 00 0F FF CD
          References