2011年9月17日 星期六

AIR3.0 Native extensions Example Part1

大家好,我是奶綠茶
Adobe AIR3.0 即將發怖
其中最酷的新功能就是可以呼叫原生的程式
在這奶綠茶我就以 Android 來做個 Demo。
1.呼叫 Android toast

2.呼叫 Android AlertDialog

3.呼叫 Android DatePickerDialog(非同步,並得到所選的日期回傳給 flash)


4.List Dialog

5.得到 DeviceID

教學Step:
1.下載 AIR3.0 SDK(目前是 RC 1 3.0.0.388)
http://labs.adobe.com/downloads/air3.html

2.安裝 FlashDevelop4
3.安裝 Ant (方便下 Command Line, 不裝也可以)
http://ant.apache.org/
4.安裝 AntPlugin for FD4
http://code.google.com/p/fd-ant-plugin/

5.FlashAction3
AIR3.0裡,多出了一個 ExtensionContext 類別,用來呼叫原生的程式碼
var extension:ExtensionContext = ExtensionContext.createExtensionContext("Native ID", null);
其中Native ID指的是你要呼叫的 id 名稱
同時要在你的 application.xml 宣告

<extensions>
<extensionID>milkmidi.air3.demo</extensionID>
</extensions>

結著就可以使用
extension.call("funcationName", ...params);
來呼叫
如果是同步的話,extendsion 就會直接 return 值
非同步的話,就使用 addEvetnListener( StatusEvent.STAUS ) 來偵聽

6.Android 端
使用 Eclipse 開啟新的 Android Project
將 AIR3.0 SDK 裡的 lib\android\FlashRuntimeExtensions.jar 加到 Complie Path 裡
public class AIR3Context extends FREContext implements FREExtension{

	private static final String TAG = "[AIR3Context]";
	
	@Override
	public FREContext createContext(String pType) {
		log(pType); // pType 的值會由 flash 端 ExtensionContext.createExtensionContext("ID" , ”這兒決定” );
		return new AIR3Context();
	}
	@Override
	public void initialize() {
		log("initialize()");
	}
	
	@Override
	public Map getFunctions() {
//注冊 function 名稱。
		HashMap result = new HashMap();
		result.put("toast", new ToastFREFunction());
		result.put("alertDialog", new AlertDialogFREFunction());
		result.put("timePickerDialog", new TimePickerDialogFREFunction());
		result.put("devices", new DevicesFREFunction());
		result.put("itemListDialog", new ItemListDialogFREFunction());
	    result.put("googleMap", new GoogleMapFREFunction());
	    return result;
	}
	
	@Override
	public void dispose() {
		log("dispose()");
	}	private void log(Object o){
		Log.i(TAG, o+"");
	}

}
將 Android 裡的 java 檔,打包成 .jar格式

7.Package Native Extensions
這裡我卡了很久,參考了許多文章和不斷的失敗,才有一些心得
要先寫一隻和 Native 呼叫用的 class,  並將其打包成 swc 格式
然後將 swc 解壓縮, 取得裡面的二個檔案
寫一隻 extension.xml 用來說明 Native , 長成這樣

<extension xmlns="http://ns.adobe.com/air/extension/2.5">
<id>milkmidi.air3.demo</id>
<versionNumber>1.0</versionNumber>
<platforms>
<platform name="Android-ARM">
<applicationDeployment>
<nativeLibrary>milkmidi.air3.demo.jar</nativeLibrary>
<initializer>milkmidi.air3.demo.AIR3Context</initializer>
<finalizer>milkmidi.air3.demo.AIR3Context</finalizer>
</applicationDeployment>
</platform>
</platforms>
</extension>
接著透過 Command line 的方法,將一堆東西打包成 xxx.ane
還好有善心人事將這一切的動作,包成了 Ant 用的 xml 格式
你只需要呼叫即可
原文如下
http://blog.aboutme.be/2011/09/12/air-native-extensions-hello-world-example-ant-script/

結論:
AIR3.0 可以呼叫原生的類別,但前提是”你還是需要自己寫原生的類別來給flash端呼叫”
想在 iOS 上用的話, 還是要乖乖寫一下 xCode。
但至少是一大進步, 其待正式版的到來。


參考文章:
http://www.leebrimelow.com/?p=2995
http://akabana.info/2011/08/11/air-native-extension-series/
http://www.adobe.com/devnet/air/articles/extending-air.html

轉載請註明出處:
http://milkmidi.blogspot.com/2011/09/air30-native-extensions-example-part1.html
AS source code
Android source code

2011年9月14日 星期三

Android Custom Title

大家好,我是奶綠茶,
今天來分享如何客制化 Android 的 Title Bar
先看預設的樣式


接著改變 Style, 變成水果風

先製作 title 的 layout, my_title.xml
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">

	<Button
	style="@style/title_bar_button_back"
	android:id="@+id/back_btn"
	android:layout_marginLeft="5dp" 
	android:text="Back"	/><!-- 這裡是 Back 鍵 -->
	
	<TextView
	style="@style/title_bar_text"
	android:id="@+id/title_txt"
	android:layout_width="match_parent"
	android:layout_height="match_parent"
	android:gravity="center"
	android:text="Title" />
	
</RelativeLayout>

style.xml
 
<style name="my_theme" parent="@android:style/Theme.Light">
		<item name="android:windowContentOverlay">@null</item>
        <item name="android:windowTitleSize">40.0dip</item>
        <item name="android:windowBackground">@drawable/iphone_bg</item>  
        <item name="android:windowTitleBackgroundStyle">@style/window_title_background_style</item>
        <item name="android:buttonStyle">@style/buttonStyle</item>
	</style>
	
	<style name="buttonStyle" parent="@android:style/Widget.Button">
		<item name="android:layout_centerVertical">true</item>
    	<item name="android:layout_width">wrap_content</item>        
        <item name="android:layout_height">wrap_content</item>
        <item name="android:minWidth">60dp</item>        
 		<item name="android:textSize">16sp</item>
 		<item name="android:textColor">#ffffffff</item>
 		<item name="android:shadowColor">#FF000000</item>
        <item name="android:shadowDx">0</item>
        <item name="android:shadowDy">-1</item>
        <item name="android:shadowRadius">0.2</item>        
		<item name="android:background">@drawable/ui_navigation_bar_default_button</item>
	</style>
	<style name="title_bar_button_back" parent="@style/buttonStyle">
 		<item name="android:background">@drawable/ui_navigation_bar_default_button_back</item>
 	</style>
	
	 <style name="window_title_background_style">
        <item name="android:gravity">center_vertical</item>
        <item name="android:layout_width">fill_parent</item>
        <item name="android:layout_height">fill_parent</item>
        <item name="android:background">@drawable/iphone_title_bar_blue</item>
    </style>
        
    <style name="title_bar_text">
 		<item name="android:textColor">#ffffff</item>
    	<item name="android:textSize">24sp</item>
    	<item name="android:shadowColor">#FF000000</item>
        <item name="android:shadowDx">0</item>
        <item name="android:shadowDy">-1</item>
        <item name="android:shadowRadius">0.2</item>
 	</style>
然後在 AndroidManifest.xml, 指定 theme 而程式碼的部份,
寫一個 Abstract 類別方便其他的 Activity 使用 其中要多判斷是否要出現 Back 鍵。
private TextView mTitleTextView;
	private Button mBackBtn;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_CUSTOM_TITLE); 		
		setContentView( getLayoutId() );	
		getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.my_title);
		
		
		
		mBackBtn = (Button) findViewById(R.id.back_btn);
		mBackBtn.setOnClickListener(new Button.OnClickListener() {			
			@Override
			public void onClick(View v) {
				finish();				
			}
		});		
		
		Intent intent = getIntent();		
		String action = intent.getAction();
		if(action!=null){
			if (action.equals(Intent.ACTION_MAIN)) {
				mBackBtn.setVisibility(View.INVISIBLE);
			}
		}	
	}
	protected abstract int getLayoutId();
	
	
	

	@Override
	public void setTitle(CharSequence title) {
		if(mTitleTextView==null){
			mTitleTextView = (TextView)findViewById(R.id.title_txt);
		}
		mTitleTextView.setText(title);
	}
 







轉載請註明出處
SourceCodeDownload

2011年9月5日 星期一

Android Save 圖片至 SD Card

大家好,我是奶綠茶
今天來分享一下如果將 Android 的畫面拍成圖檔並存在 SD Card 裡
首先要在 Manifest.xml 裡開啟 寫入的權限
uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
接著要把 View 轉成 Bitmap 物件
final ViewGroup _v = (ViewGroup) findViewById(R.id.root);
Bitmap bm = Bitmap.createBitmap(_v.getWidth(), _v.getHeight(),	Bitmap.Config.RGB_565);
_v.draw(new Canvas(bm));
透過 File 來存檔 先檢查使用者有沒有 SD Card
public static boolean checkSDCard() {
    		if (Environment.getExternalStorageState().equals(
    				Environment.MEDIA_MOUNTED)) {
    			return true;
    		}
    		return false;
    	}
存檔
public static void saveBitmap(String pFolderPath, Bitmap pBitmap,
    			String pFileName) throws IOException {
    		
    		String _folderPath = pFolderPath;
    		if (_folderPath.lastIndexOf("/") == -1) {
    			_folderPath += "/";
    		}
    		File _file = new File(_folderPath + pFileName);
    		OutputStream _outStream  = new FileOutputStream(_file);

    		pBitmap.compress(Bitmap.CompressFormat.JPEG, 90, _outStream);
    	
    		_outStream.flush();
    		_outStream.close();
    	}
// 自動檔名依日期
public static String getTimeName() {
    		Date _date = new Date(System.currentTimeMillis());
    		SimpleDateFormat _sdf = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss");
    		Random _random = new Random();
    		return _sdf.format(_date) + _random.nextInt(999);
    	}
其中會遇到一個小問題,當你這樣存檔時,
再進入 Android 預設的圖片庫時,會找不到那張圖片
Google 了一下,發現要呼叫 MediaScannerConnection 來更新
讓 Android 知道
原文連結: 點我
這樣就完成啦。

轉載請註明出處 SourceCodeDownload

2011年9月4日 星期日

Android ImageView ScaleType

大家好,我是奶綠茶
在 Android 裡的 ImageView 元件,可以放置圖片
其中可以設定 ScaleType
官方 API 說明

為了方便測試,在這先準備二張圖片
450x500和 500x450
筆者以 320x480 的 Emulator 來測試

Layout 的部份放上二個 RadioButton 用來切換二圖不同 Size 的圖片
再放上六個 Button 來顯示圖片同 Size 的圖片 再放上六個 Button 來顯示圖片
主程式
package milkmidi.tutorial.imagescaletype;

import android.app.Activity;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager.LayoutParams;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.PopupWindow;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.TextView;

public class ImageViewScaleTypeMainActivity extends Activity implements OnCheckedChangeListener {
	

	Drawable mCurrentDrawable;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
     
        RadioGroup radioGroup = (RadioGroup) findViewById(R.id.radio_group);
        radioGroup.setOnCheckedChangeListener(this);
        onCheckedChanged(null,R.id.radio_450x500);
    }
    @Override
	public void onCheckedChanged(RadioGroup group, int checkedId) {
    	switch (checkedId) {
			case R.id.radio_450x500:	
				mCurrentDrawable = getResources().getDrawable(R.drawable.a450x500); 
				break;
			case R.id.radio_500x450:	
				mCurrentDrawable = getResources().getDrawable(R.drawable.a500x450); 
				break;
		}		
	}    
    public void onClick(View v){
    	ScaleType scaleType = null;
    	switch (v.getId()) {
			case R.id.center_btn:	
				scaleType = ScaleType.CENTER;
				break;
			case R.id.center_crop_btn:
				scaleType = ScaleType.CENTER_CROP;
				break;
			case R.id.center_inside_btn:	
				scaleType = ScaleType.CENTER_INSIDE;
				break;
			case R.id.fit_center_btn:		
				scaleType = ScaleType.FIT_CENTER;
				break;
			case R.id.fit_end_btn:			
				scaleType = ScaleType.FIT_END;
				break;
			case R.id.fit_start_btn:		
				scaleType = ScaleType.FIT_START;
				break;
			case R.id.fit_xy_btn:			
				scaleType = ScaleType.FIT_XY;
				break;
			case R.id.matrix_btn:			
				scaleType = ScaleType.MATRIX;
				break;
		}    	
    	
    	ViewGroup view = (ViewGroup)getLayoutInflater().inflate(R.layout.image_view, null);
    	TextView tf = (TextView) view.findViewById(R.id.title_txt);
    	tf.setText(scaleType.toString());
    	
    	ImageView image = (ImageView)view.findViewById(R.id.image_view);
    	image.setImageDrawable(mCurrentDrawable);
    	image.setScaleType(scaleType);
    	PopupWindow pop = new PopupWindow(
    			view,
    			LayoutParams.FILL_PARENT,
				LayoutParams.FILL_PARENT, 
				true);
    	pop.setContentView(view);
    	pop.setBackgroundDrawable(new ColorDrawable(0x5500ff00));
    	pop.showAtLocation(findViewById(R.id.root), Gravity.TOP, 0, 0);
    	pop.update();
    }


	
}


CENTER  Center the image in the view, but perform no scaling.
圖中置中,但不縮放





CENTER_CROP  Scale the image uniformly (maintain the image's aspect ratio) so that both dimensions (width and height) of the image will be equal to or larger than the corresponding dimension of the view (minus padding).
等比縮放,將超出範圍的切掉




CENTER_INSIDE  Scale the image uniformly (maintain the image's aspect ratio) so that both dimensions (width and height) of the image will be equal to or less than the corresponding dimension of the view (minus padding).
等比縮放,讓圖片縮至容器裡




FIT_CENTER  Scale the image using CENTER.
等比縮放,將圖片放在容器裡的正中間




FIT_END  Scale the image using END.
等比縮放,將圖片放在容器裡的下方




FIT_START  Scale the image using START.
等比縮放,將圖片放在容器裡的上方




FIT_XY  Scale the image using FILL.
整個稱滿容器,不會等比縮放





MATRIX  Scale using the image matrix when drawing.
研究中


轉載請註明出處
SourceCodeDownload