2011年7月14日 星期四

Google發布Android NDK, Revision 6

Google近日已發布Android NDK, Revision 6版本,該版本主要增加了X86系統支援,另外還有ndk-stack工具,該工具可以在logcat看到除錯訊息(圖1)改善了先前版本只能看到address訊息(圖2),詳細及使用方式在docs/NDK-STACK.html.
圖1:

圖2:

2011年7月8日 星期五

[Android Messenger] 不用AIDL也能設計具備IPC能力的遠程服務應用程式

我們在 運用AIDL來打造Android程序間的通訊 文章中介紹如何利用AIDL(Android Interface Definition Language)來設計具備IPC(Interprocess Communication)能力的應用程式的文章,您如果對於AIDL有興趣可以參閱,Chapter 14. Android Interface Definition Language
若是您覺得用AIDL實在是太麻煩了,可以參考ApiDemo範例中的MessengerServiceActivities.java及MessengerService.java。

1. 先建立專案


2. 專案結構


3. MessengerServiceActivities.java整體程式摘要

4. MessengerServiceActivities.java訊息處理程式

5. MessengerService.java整體程式摘要

6. MessengerService.java 訊息處理程式


詳細的程式請參考ApiDemo範例。

2011年7月3日 星期日

iPhone 教學資源分享


iPhone 開發筆記
iphone app 開發 (一) - 基本概念

iphone app 開發 (三十八) 多重檢視動畫 (animations)

iphone app 開發 (三十九) 實做分頁控制

iphone app 開發 (四十) Core Location 地理位置資訊偵測

iphone app 開發 (四十二) 三軸加速感應器之觀念

iphone app 開發 (四十三) 亂數結合搖晃互動功能

iphone app 開發 (四十四) 行銷你的 App 應用程式 !

2011年6月27日 星期一

[ Android min3d] min3d測試心得及下載網址

最近一直關心Android/Blender計畫,簡稱AB計畫。我找到一個很不錯的軟體工具min3d,下載網址如下:


經測試其重要範例執行畫面如下:









































































































2011年6月11日 星期六

[Android Sensor] 感測器模擬軟體的使用

下載sensorsimulator-1.1.1.zip放在http://code.google.com/p/openintents/downloads/detail?name=sensorsimulator-1.1.1.zip&can=2&q=


以前的文章 利用感測器模擬程式來開發感測器應用程式,發表在http://cheng-min-i-taiwan.blogspot.com/2010/03/blog-post_26.html

使用sensorsimulator-1.1.1,修改ApiDemo在com.example.android.apis.os套件下Sensors程式,藍色字為修訂的程式。

package com.example.sensors;

import org.openintents.sensorsimulator.hardware.Sensor;
import org.openintents.sensorsimulator.hardware.SensorEvent;
import org.openintents.sensorsimulator.hardware.SensorEventListener;
import org.openintents.sensorsimulator.hardware.SensorManagerSimulator;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.hardware.SensorListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.view.View;

public class Sensors extends Activity {
/** Tag string for our debug logs */
private static final String TAG = "Sensors";

private SensorEventListener mEventListenerAccelerometer;
private SensorEventListener mEventListenerLight;
private SensorEventListener mEventListenerTemperature;
private SensorEventListener mEventListenerOrientation;
private SensorEventListener mEventListenerMagneticField;

//private SensorManager mSensorManager;

private SensorManagerSimulator mSensorManager;

private GraphView mGraphView;

private class GraphView extends View implements SensorListener
{
private Bitmap mBitmap;
private Paint mPaint = new Paint();
private Canvas mCanvas = new Canvas();
private Path mPath = new Path();
private RectF mRect = new RectF();
private float mLastValues[] = new float[3*2];
private float mOrientationValues[] = new float[3];
private int mColors[] = new int[3*2];
private float mLastX;
private float mScale[] = new float[2];
private float mYOffset;
private float mMaxX;
private float mSpeed = 1.0f;
private float mWidth;
private float mHeight;

public GraphView(Context context) {
super(context);
mColors[0] = Color.argb(192, 255, 64, 64);
mColors[1] = Color.argb(192, 64, 128, 64);
mColors[2] = Color.argb(192, 64, 64, 255);
mColors[3] = Color.argb(192, 64, 255, 255);
mColors[4] = Color.argb(192, 128, 64, 128);
mColors[5] = Color.argb(192, 255, 255, 64);

mPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
mRect.set(-0.5f, -0.5f, 0.5f, 0.5f);
mPath.arcTo(mRect, 0, 180);
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.RGB_565);
mCanvas.setBitmap(mBitmap);
mCanvas.drawColor(0xFFFFFFFF);
mYOffset = h * 0.5f;
mScale[0] = - (h * 0.5f * (1.0f / (SensorManager.STANDARD_GRAVITY * 2)));
mScale[1] = - (h * 0.5f * (1.0f / (SensorManager.MAGNETIC_FIELD_EARTH_MAX)));
mWidth = w;
mHeight = h;
if (mWidth < mHeight) {
mMaxX = w;
} else {
mMaxX = w-50;
}
mLastX = mMaxX;
super.onSizeChanged(w, h, oldw, oldh);
}

@Override
protected void onDraw(Canvas canvas) {
synchronized (this) {
if (mBitmap != null) {
final Paint paint = mPaint;
final Path path = mPath;
final int outer = 0xFFC0C0C0;
final int inner = 0xFFff7010;

if (mLastX >= mMaxX) {
mLastX = 0;
final Canvas cavas = mCanvas;
final float yoffset = mYOffset;
final float maxx = mMaxX;
final float oneG = SensorManager.STANDARD_GRAVITY * mScale[0];
paint.setColor(0xFFAAAAAA);
cavas.drawColor(0xFFFFFFFF);
cavas.drawLine(0, yoffset, maxx, yoffset, paint);
cavas.drawLine(0, yoffset+oneG, maxx, yoffset+oneG, paint);
cavas.drawLine(0, yoffset-oneG, maxx, yoffset-oneG, paint);
}
canvas.drawBitmap(mBitmap, 0, 0, null);

float[] values = mOrientationValues;
if (mWidth < mHeight) {
float w0 = mWidth * 0.333333f;
float w = w0 - 32;
float x = w0*0.5f;
for (int i=0 ; i<3 ; i++) {
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.translate(x, w*0.5f + 4.0f);
canvas.save(Canvas.MATRIX_SAVE_FLAG);
paint.setColor(outer);
canvas.scale(w, w);
canvas.drawOval(mRect, paint);
canvas.restore();
canvas.scale(w-5, w-5);
paint.setColor(inner);
canvas.rotate(-values[i]);
canvas.drawPath(path, paint);
canvas.restore();
x += w0;
}
} else {
float h0 = mHeight * 0.333333f;
float h = h0 - 32;
float y = h0*0.5f;
for (int i=0 ; i<3 ; i++) {
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.translate(mWidth - (h*0.5f + 4.0f), y);
canvas.save(Canvas.MATRIX_SAVE_FLAG);
paint.setColor(outer);
canvas.scale(h, h);
canvas.drawOval(mRect, paint);
canvas.restore();
canvas.scale(h-5, h-5);
paint.setColor(inner);
canvas.rotate(-values[i]);
canvas.drawPath(path, paint);
canvas.restore();
y += h0;
}
}

}
}
}

public void onSensorChanged(int sensor, float[] values) {
//Log.d(TAG, "sensor: " + sensor + ", x: " + values[0] + ", y: " + values[1] + ", z: " + values[2]);
synchronized (this) {
if (mBitmap != null) {
final Canvas canvas = mCanvas;
final Paint paint = mPaint;
if (sensor == SensorManager.SENSOR_ORIENTATION) {
for (int i=0 ; i<3 ; i++) {
mOrientationValues[i] = values[i];
}
} else {
float deltaX = mSpeed;
float newX = mLastX + deltaX;

int j = (sensor == SensorManager.SENSOR_MAGNETIC_FIELD) ? 1 : 0;
for (int i=0 ; i<3 ; i++) {
int k = i+j*3;
final float v = mYOffset + values[i] * mScale[j];
paint.setColor(mColors[k]);
canvas.drawLine(mLastX, mLastValues[k], newX, v, paint);
mLastValues[k] = v;
}
if (sensor == SensorManager.SENSOR_MAGNETIC_FIELD)
mLastX += mSpeed;
}
invalidate();
}
}
}

public void onAccuracyChanged(int sensor, int accuracy) {
// TODO Auto-generated method stub

}
}

/**
* Initialization of the Activity after it is first created. Must at least
* call {@link android.app.Activity#setContentView setContentView()} to
* describe what is to be displayed in the screen.
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
// Be sure to call the super class.
super.onCreate(savedInstanceState);

// mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
mSensorManager = SensorManagerSimulator.getSystemService(this,
SENSOR_SERVICE);
mSensorManager.connectSimulator();

mGraphView = new GraphView(this);
setContentView(mGraphView);

initListeners();

}

private void initListeners() {
mEventListenerAccelerometer = new SensorEventListener() {

@Override
public void onSensorChanged(SensorEvent event) {
float[] values = event.values;
mGraphView.onSensorChanged(SensorManager.SENSOR_MAGNETIC_FIELD, values);

// mTextView1.setText("Accelerometer: " + values[0] + ", "
// + values[1] + ", " + values[2]);

}

@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
mEventListenerMagneticField = new SensorEventListener() {

@Override
public void onSensorChanged(SensorEvent event) {
float[] values = event.values;
// mTextView2.setText("Compass: " + values[0] + ", " + values[1]
// + ", " + values[2]);
}

@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
mEventListenerOrientation = new SensorEventListener() {

@Override
public void onSensorChanged(SensorEvent event) {
float[] values = event.values;
mGraphView.onSensorChanged(SensorManager.SENSOR_ORIENTATION, values);
// mTextView3.setText("Orientation: " + values[0] + ", "
// + values[1] + ", " + values[2]);
}

@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
mEventListenerTemperature = new SensorEventListener() {

@Override
public void onSensorChanged(SensorEvent event) {
float[] values = event.values;
// mTextView4.setText("Temperature: " + values[0] + ", "
// + values[1] + ", " + values[2]);
}

@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
mEventListenerLight = new SensorEventListener() {

@Override
public void onSensorChanged(SensorEvent event) {
float[] values = event.values;
// mTextView5.setText("Light: " + values[0]);
}

@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
}

@Override
protected void onResume() {
super.onResume();

/* mSensorManager.registerListener(mGraphView,
SensorManager.SENSOR_ACCELEROMETER |
SensorManager.SENSOR_MAGNETIC_FIELD |
SensorManager.SENSOR_ORIENTATION,
SensorManager.SENSOR_DELAY_FASTEST);*/
mSensorManager.registerListener(mEventListenerAccelerometer,
mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_FASTEST);
mSensorManager.registerListener(mEventListenerMagneticField,
mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),
SensorManager.SENSOR_DELAY_FASTEST);
mSensorManager.registerListener(mEventListenerOrientation,
mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION),
SensorManager.SENSOR_DELAY_FASTEST);
mSensorManager.registerListener(mEventListenerTemperature,
mSensorManager.getDefaultSensor(Sensor.TYPE_TEMPERATURE),
SensorManager.SENSOR_DELAY_FASTEST);
mSensorManager.registerListener(mEventListenerLight,
mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT),
SensorManager.SENSOR_DELAY_FASTEST);

}

@Override
protected void onStop() {

// mSensorManager.unregisterListener(mGraphView);
mSensorManager.unregisterListener(mEventListenerAccelerometer);
mSensorManager.unregisterListener(mEventListenerMagneticField);
mSensorManager.unregisterListener(mEventListenerOrientation);
mSensorManager.unregisterListener(mEventListenerTemperature);
mSensorManager.unregisterListener(mEventListenerLight);

super.onStop();
}
}

2011年6月10日 星期五

[Android UI 教學(7)] 記憶上次執行結果

1. 在紅色方塊處按下mouse右鍵,選擇source再選擇Override/Implement Methods


2.輸入程式

package com.example.sum;

import android.app.Activity;

import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;

import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class SumActivity extends Activity {
/** Called when the activity is first created. */

private String PREF_NUM1="NUM1";
private String PREF_NUM2="NUM2";
private String PREF_SUM="SUM";

EditText et1, et2;
Button bt;
TextView tv;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
et1 = (EditText) findViewById(R.id.EditText01);
et2 = (EditText) findViewById(R.id.EditText02);
tv = (TextView) findViewById(R.id.TextView01);
bt = (Button) findViewById(R.id.Button01);

bt.setOnClickListener(new OnClickListener(){

@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
double d1,d2;
d1 = Double.parseDouble(et1.getText().toString());
d2 = Double.parseDouble(et2.getText().toString());
tv.setText(Double.toString(d1+d2));
}

});
}
@Override
protected void onPause() {
// TODO Auto-generated method stub

SharedPreferences pref = getSharedPreferences ("pref_apn" , MODE_PRIVATE);
Editor ed = pref.edit();
ed.putString(PREF_NUM1, et1.getText().toString());
ed.putString(PREF_NUM2, et2.getText().toString());
ed.putString(PREF_SUM, tv.getText().toString());
ed.commit();

super.onPause();
}
@Override
protected void onResume() {
// TODO Auto-generated method stub

SharedPreferences pref = getSharedPreferences("pref_apn" , MODE_PRIVATE);
et1.setText(pref.getString(PREF_NUM1, ""));
et2.setText(pref.getString(PREF_NUM2, ""));
tv.setText(pref.getString(PREF_SUM, ""));

super.onResume();
}

}

3. 在編輯框內輸入資料,然後離開程式,再執行程式,您會發現上次輸入狀態還在。