總網頁瀏覽量

2013年4月14日 星期日

SensorManager

SensorManager是手機平板電腦特有的功能


本文先說明加速度感測器:
加速度感測器顯示手機受到加速度的方向
分成X Y Z三個方向

將手機平躺著那麼X 與Y加速度趨近於零
Z加速度為9.8m/s^2

如果將手機直立Y加速度為9.8m/s^2
將手機橫立X軸加速度為9..8m/s^2

只是單純旋轉手機,不出力那麼所受的合力為9.8m/s^2




public class MainActivity extends Activity {
private SensorManager mgr;
private TextView info;
private Sensor sensor;
private MyListener listener;
private int nowz = -500, nowx, initx;
private float maxx;
private boolean isPull;
private int iscast = 0;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

info = (TextView) findViewById(R.id.info);

mgr = (SensorManager) getSystemService(SENSOR_SERVICE);
List<Sensor> list = mgr.getSensorList(Sensor.TYPE_ALL);

// for (Sensor sensor: list){
// info.append(sensor.getName() + ":" +
// sensor.getMaximumRange() + ":" +
// sensor.getResolution() + "\n"
// );
// }

//
sensor = mgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
//
// sensor = mgr.getDefaultSensor(Sensor.TYPE_ORIENTATION);

// sensor = mgr.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);
// sensor = mgr.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
// sensor = mgr.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);
listener = new MyListener();

}

@Override
protected void onResume() {
super.onResume();
mgr.registerListener(listener, sensor, SensorManager.SENSOR_DELAY_NORMAL);
}

@Override
protected void onPause() {
super.onPause();
mgr.unregisterListener(listener);
}

private class MyListener implements SensorEventListener {

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

}

@Override
public void onSensorChanged(SensorEvent event) {
float[] data = event.values;
float x = data[0] * 10, z = data[2] * 100;
// info.setText(data[0]+"\n"+data[2]);

if (z < nowz) {


if (iscast == 0) {
Log.i("log", "以拉釣竿");
nowz = 990;
iscast = 1;
}

}

if (z > nowz) {
if (iscast == 1) {
if (x < 0) {

maxx = (Math.abs(1-x/10))*5;
Log.i("log", "z"+z + " x"+x);
info.setText("" + maxx);
iscast = 3;
}
}
maxx = 0;
initx = -20;
nowz = -500;

}

// if (z < nowz) {
// nowz = (int) z * 10;
// initx = (int) x;
// isPull = true;
// } else {
// isPull = false;
// if (x < initx) {
// int dx = (int) (Math.abs(x - initx));
// if (dx > maxx) {
// maxx = dx;
// info.setText("Power:" + maxx);
// }
// } else {
// nowz = 999;
// maxx = 0;
// }
// }
}}}




SensorManager.getOrientation();

Dialog(AlertDialog,ProgressDialog,自訂dialog,自訂Toast,View)

本文是AlertDialgo的實作
基本上當作SOP處理
記得實作AlertDialog基本架構


AlertDialog是一個類別,裡面包住Builder類別
AlertDialog是Dialog子類別。

本例子
全都用Button來觸動showDialog method


首先在Activity宣告AlertDialog的物件。
private AlertDialog alert;


一、true與false對話框:

private void showDialog1(){

AlertDialog.Builder builder = new AlertDialog.Builder(this);
//宣告AlertDialog裡的Builder物件
////this 是指Activity也就是對話框顯示所在的Activity,this為context型態

builder.setTitle("這是對話框標題");
builder.setMessage("這是對話框內容。是否刪除資料?");
builder.setCancelable(false);
//設定鎖住返回鍵,false表示禁止按下返回鍵,只能按"確定"與"取消"

//alertDidalog的"確認"按鈕,傳遞參數,按鈕的內容以及註冊傾聽者。實作傾聽者匿名內部類別。
builder.setPositiveButton("是", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(MainActivity.this,"資料已刪除",Toast.LENGTH_SHORT).show();
//由於Toast包在內部類別裡面所以this前面要加上MainActivity
//記得要加上show()
}
});

//alertDidalog的"取消"按鈕,其餘同上
builder.setNegativeButton("否", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(MainActivity.this, "取消刪除", Toast.LENGTH_SHORT).show();
}
});

//最後務必記得要create() 跟show()
alert=builder.create();//create傳回Builder型態
alert.show();//.show() 傳回Dialog型態

}



二、列表式(list)對話框:按下button顯示多個項目,點其中一個項目,告知使用者所選的項目。
核心method :setItems(CharSequence[],DialogInterface.OnClickListener);

String items={"香蕉","芭樂","手榴彈","書"};


private void showDialog2(){
AlertDialog.Builder builder = new AlertDialog.Builder(this);

builder.setTitle("選擇一個喜歡的項目吧");
builder.setCancelable(true);

builder.setItems(items,new DialogInterface.OnClickListener() {
//傳入字串陣列items
@Override
public void onClick(DialogInterface dialog, int which) {
//which表示使用者所點選的項目
Toast.makeText(MainActivity.this, "你選擇了"+items[which], Toast.LENGTH_SHORT).show();
}
});
alert=builder.create();
alert.show();

}



三、自訂對話框:利用xml自訂對話框,與Dialog物件結合。Dialog是AlertDialog父類別。


private Dialog dialog;


private void showDialog3(){
dialog = new Dialog(this);
//對話框物件,this是context物件,表示對話框所在activity
dialog.setContentView(R.layout.newreg);//配接對話框
dialog.setTitle("註冊新帳號");

Button ok , cancel;
// ok=(Button)findViewById(R.id.ok);
//必須指定是哪個Activity、Dialog在findViewById,否則會出現NullPointerException,找不到對應物件。
ok = (Button)dialog.findViewById(R.id.ok);
//使用dialog下的findviewbyid
cancel = (Button)dialog.findViewById(R.id.cancel);
username = (EditText)dialog.findViewById(R.id.username);
passwd = (EditText)dialog.findViewById(R.id.passwd);

ok.setOnClickListener(new OnClickListener(){

@Override
public void onClick(View v) {
String uname = username.getText().toString();
String password=passwd.getText().toString();

Toast.makeText(MainActivity.this, uname+":"+password, Toast.LENGTH_SHORT).show();
dialog.dismiss();//解散(關閉)對話框
}});

cancel.setOnClickListener(new OnClickListener(){

@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "cancel", Toast.LENGTH_SHORT)
.show();
dialog.dismiss();
}});
dialog.show();//別忘了要show()
}




四、ProgressDialog:
實作下載檔案時常會出現的對話框
宣告ProgressDialog物件
利用執行緒計算count、Handler處理長條bar的運作

private ProgressDialog progress;
private MyHandler handler = new MyHandler();

//private Handler handler;
//打錯,造成NullPointerException
//記得要new MyHandler();否則也會造成NullPointerException





private void showDialog4(){

progress = new ProgressDialog(this);
progress.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
//progress.setProgressStyle(ProgressDialog.STYLE_SPINNER);
//Spinner表示畫圓圈,Horizontal表示長條bar
progress.setCancelable(false);
progress.setMessage("Loading.....");
progress.setMax(123);//長條bar最大長度


new MyThread().start();

progress.show();

}

private class MyThread extends Thread{
@Override
public void run() {
for(int i=0;i<=123;i++){
//改成i+=2  長條bar只會跑到122就停止

handler.sendEmptyMessage(i);
//忘了打這行造成,progressDialog只開啟視窗卻沒有跑

//progress.setProgress(i);
//其實可以直接在thread處理也有同樣效果,但忘了為何在Handler處理會比較好

try {
Thread.sleep(60);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}


}

progress.dismiss();
}
}


private class MyHandler extends Handler{

@Override
public void handleMessage(Message msg)
{
progress.setProgress(msg.what);//傳入參數設定長條bar的值
if(msg.what==progress.getMax()){
progress.dismiss();

}
}

}


五、自訂View並將View鑲嵌進Toast,變成自訂Toast

利用context提供的method getLayoutInflater建立自訂view
LayoutIflater inflater= getLayoutInflater()



private void showMyToast(int status , String info){

LayoutInflater inflater = getLayoutInflater();
//Activity的method
//將自己設計的layout轉成View

View layout = inflater.inflate(R.layout.mytoast, (ViewGroup)findViewById(R.id.root));
//R.id.root是xml中layout的id
//將xml檔mytoast裡面的ViewGroup(Layout及其元件)轉成View
//setContentView(layoutID)會直接將layout貼上畫面


ImageView img = (ImageView)layout.findViewById(R.id.img);
TextView msg= (TextView)layout.findViewById(R.id.msg);

//注意Img跟msg是屬於變數layout裡面的
//所以是layout之中findview,不是MainActivity findview


switch(status){

case 1:

img.setImageResource(R.drawable.warning);
break;

case 2:
img.setImageResource(R.drawable.warning);
break;

default:
img.setImageResource(R.drawable.warning);
break;


}

msg.setText(info);
//TextView mag秀出文字

Toast toast = new Toast(this);

toast.setView(layout);//將自訂view放入toast
toast.setGravity(Gravity.CENTER_VERTICAL, 0, 100);
//(,xoffset,yoffset)
//設置toast的位置

toast.setDuration(Toast.LENGTH_SHORT);
toast.show();

}


六、另一種自訂View

另一種自訂View是將java鑲嵌到layout檔案
在java檔案中寫class繼承view
在layout寫
<com.example.signature.MainPanel  

 />

2013年4月11日 星期四

android 資料儲存data storage

SharedPreference:


儲存基本型態的資料
如果應用程式使用的資料量不大
那麼可以考慮用SharedPreference

應用:
遊戲的紀錄
聲音開與關
等程式相關狀態


用SharedPreference創立的資料只限於該應用程式使用
當然可以在getSharedPreferences設定公開檔案給其他應用程式使用
SharedPreferences sp = getSharedPreferences("YYP.dat",MODE_PRIVATE);

以XML格式將資料存放到/data/data/com.example.fishingmapmaker/shared_prefs/之下

如果在實體手機操作那麼
/data必須是root權限才可以讀取





public class MainActivity extends Activity {

private Button click1, click2, click3;
private TextView tv, tv2, tv3;
private EditText iodata1, iodata3;

private SharedPreferences sp;
//宣告sharedpreference物件
private SharedPreferences.Editor editor;
//宣告sharedpreference編輯器

private String username;
private int stage;
private boolean sound;


protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

sp = getSharedPreferences("YYPdata", MODE_PRIVATE);
         //getSharedPreferences是context裡面的method
                //建立sharedpreference儲存資料的檔案   並宣告存取權限為只限於本程式閱讀

editor= sp.edit();
//調出sharedpreference編輯器

click1 = (Button)findViewById(R.id.click1);
tv = (TextView)findViewById(R.id.tv);

click2 = (Button)findViewById(R.id.click2);
tv2 = (TextView)findViewById(R.id.tv2);
iodata1 = (EditText)findViewById(R.id.iodata1);

click3 = (Button)findViewById(R.id.click3);
tv3 = (TextView)findViewById(R.id.tv3);
iodata3 = (EditText)findViewById(R.id.iodata3);



click1.setOnClickListener(new OnClickListener(){

@Override
public void onClick(View arg0) {
savePreference();
}
});
readPreference();
click2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
saveInnerData();
}
});

readInnerData();

click3.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
saveSDData();
}
});

readSDData();


}


private void savePreference(){
editor.putBoolean("sound", false);//每個資料型態都有對應的method
editor.putString("username", "Brad");//存進檔案
editor.putInt("stage", 118);

editor.commit();//務必要寫這行,才會將資料存進檔案
readPreference();

}


private void readPreference(){
username = sp.getString("username", "nobody");//讀取sharedpreference的儲存內容
stage=sp.getInt("stage", 0);
sound=sp.getBoolean("sound", true);

tv.setText("UserName: " +  username + "\n" +
"Sound: " + (sound?"On":"Off") + "\n" +
"Stage: " + stage);

}

private void saveInnerData(){
String data = iodata1.getText().toString();//EditView的輸入文字記得要在末端加上toString(),因為getText()是View型態

try{
FileOutputStream fout

FileOutputStream fout = openFileOutput("YYP.dat",MODE_PRIVATE);
FileOutputStream fout= new FileOutputStream("YYP.dat");//錯誤寫法 filenotfound
//在純翠java 會預設純到專案跟目錄 

fout.write(data.getBytes());//因為檔案皆為字串所以要將字串型別轉成byte型式

fout.flush();
fout.close();
Toast.makeText(this, "save OK", Toast.LENGTH_SHORT).show();
readInnerData();

}catch(IOException e){

Toast.makeText(this,"IO Exception", Toast.LENGTH_SHORT).show();
}

}
private void readInnerData(){

try{
// FileInputStream fin = new FileInputStream("YYP.dat");//出現fileNotFoundException
FileInputStream fin = openFileInput("YYP.dat");
BufferedReader reader = new BufferedReader(new InputStreamReader(fin));
String line;
while((line=reader.readLine())!=null){
tv.append(line+"\n");


}

fin.close();
}catch(IOException e){

Toast.makeText(this,"save ok",Toast.LENGTH_SHORT ).show();
}



}


//讀取寫入SDcard

private void saveSDData(){
String data = iodata3.getText().toString();
try{
FileWriter writer = new FileWriter("/mnt/sdcard/brad.dat");

writer.write(data);
writer.flush();
writer.close();

}catch(IOException e){

e.printStackTrace();

}

}


private void readSDData(){
try{
BufferedReader reader = new BufferedReader(new FileReader("/mnt/sdcard/brad.dat"));
String line;
while((line=reader.readLine())!=null){
tv3.append(line+"\n");

}
reader.close();
}catch(Exception e){


}

}


}





InnerStorage:

inner storage儲存在/data/data/com.example/files/之下


SDcardStorage
將資料儲存在SDcard

2013年4月10日 星期三

android Tiemrtask

除了extends Thread 、implement Runnable之外
也可以用timertask物件啟動執行緒

並且可以採用Button按下去會執行多個執行緒


在一般java swing可以直接在thread 的run()中直接操控UI
但是在android不行
必須裡用handler傳遞message操控UI


private Timer timer;
pirvate MyHandler handler;
timer.schedule(timertask,什麼時候執行,執行時間長度);





private void Click3(){
timer = new Timer();
// timer.schedule(task, when, period)
timer.schedule(new MyTask(),0,1000);
//第零秒後執行my task物件,持續執行一千秒,每秒執行一次
}

private class MyTask extends TimerTask{
int i;
@Override
public void run() {
Log.i("YYP","i = "+i++);
// tv.setText("i = "+i++);
//在android裡面thread不可以直接操控UI否則會出現
//04-10 23:31:45.967: W/dalvikvm(399): threadid=7: thread exiting with uncaught exception (group=0x4001d800) 04-10 23:31:46.009: E/AndroidRuntime(399): FATAL EXCEPTION: Timer-0 //04-10 23:31:46.009: E/AndroidRuntime(399): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. 

//要操控UI必須用handler物件傳遞Message
handler.sendEmptyMessage(i++);
//handler.sendEmtyMessage(what);
}
}

//handler必須宣告,UI所在的activity之中。
private class MyHandler extends Handler{

//reciev Message
@Override
public void handleMessage(Message msg) {
tv.setText("i="+msg.what);
}


}

//activity結束時,取消timer物件執行緒
//否則activity結束後timer物件仍會持續執行
public void finish(){
timer.cancel();
timer=null;
super.finish();


}

2013年4月8日 星期一

事件處理

Java事件處理採取"委派事件模式"(delegation event model)。
委派事件模式:當事件發生時,產生事件的物件(event source)會將此一"訊息"轉給"事件傾聽者"(event listener)處理的一種方式。

訊息:java.awt.event事件類別庫裡的事件物件。

ex:按下Button會觸發一個動作事件,java產生一個"事件物件",將事件物件傳遞給事件傾聽者,事件傾聽者再將事件物件的種類將工作指派給事件處理者。


一個程式裡面允許多個事件傾聽者,為了讓"產生事件的物件"知道要將事件訊息傳送到哪一個"事件傾聽者",我們必須先把"事件傾聽者"向產生事件的物件註冊(register)。

事件傾聽者由"包含事件來源者"的物件擔任。
該物件必須實作implements ActionListener事件處理介面



事件類別有很多種

每個事件類別都有相對應的事件傾聽者

事件處理者包在事件傾聽者介面中,事件處理者是一堆method。

2013年4月7日 星期日

Java UI

import java.awt.*;  //使用視窗物件Frame 必須Import

Frame frm = new Frame("Window Title");//建立視窗物件,附上標題
frm.setSize(100,200);
frm.setBackground(Color.blue);
frm.setLocation(200,300);//視窗的位置
frm.setVisible(true);//讓視窗印在螢幕上


或者是
class XXX extnds Frame{

XXX frm = new XXX();

frm.setTitle("");
frm.setSize(100,200);
frm.setLocation(200,300);
frm.setVisible(true);


}



import java.awt.*;

public class UITest {
    static Frame frm= new Frame("label class");
    static Label lab = new Label();
    //label亂碼問題
    //file→project property→endocing選x-windows-950或x-MS950-SCS
   //這是netBean解決方法
    static Button btn = new Button("click me");
    static Checkbox ckb1= new Checkbox("電腦",true);
    static Checkbox ckb2= new Checkbox("人腦");
    static Checkbox ckb3= new Checkbox("豬腦",true);
 
    static Checkbox ckb4= new Checkbox("劉邦");
    static Checkbox ckb5 = new Checkbox("蕭何");
 
 
    public static void main(String[] args) {
      frm.setLayout(null);//加上這行就可以看到原來視窗底色
        frm.setSize(400, 300);
        frm.setBackground(Color.pink);
        lab.setText("初出茅廬");
        lab.setBackground(Color.gray);
       //執行結果只會看到灰色占滿版面,因為awt預設版面配置
        //將物件放大到與視窗同樣大小
        lab.setAlignment(Label.CENTER);
 //       lab.setForeground(Color.red);
   lab.setForeground(new Color(0xE12A94)); //自己建立color物件 設定顏色        
        lab.setLocation(50, 60);//設定label大小 位置
        lab.setSize(100,50);//上面的frm.setLayout(null);再加上這兩行才會正確顯示label位置大小
        Font fnt = new Font("新細明體",Font.ITALIC+Font.BOLD,22);//自型、style、size
        lab.setFont(fnt);              
        frm.add(lab);
       // lab.setVisible(true);

     
        btn.setBounds(100, 120, 70, 50);
        btn.setForeground(Color.red);
        btn.setBackground(Color.green);
        frm.add(btn);
//==============複選的checkbox作法 ,個別建立checkbox物件=====//      
//        ckb1.setSize(100, 50);
//        ckb2.setSize(100,50);
//        ckb3.setSize(100, 50);
//        ckb1.setLocation(200, 160);
//        ckb2.setLocation(200,200);
//        ckb3.setLocation(200, 230);
     
        ckb1.setBounds(200, 160, 100, 50);
        ckb2.setBounds(200, 200, 100, 50);
        ckb3.setBounds(200, 230, 100, 50);
        frm.add(ckb1);
        frm.add(ckb2);
        frm.add(ckb3);
     
//=========單選的checkbox作法,建立checkbox群組物件,設定checkbox屬於群組物件      
    CheckboxGroup grp = new CheckboxGroup();
    ckb4.setBounds(300, 200, 100, 50);
    ckb5.setBounds(300, 230, 100, 50);
        ckb4.setCheckboxGroup(grp);//將ckb4設定為grp的群組物件
        ckb5.setCheckboxGroup(grp);
     
        ckb4.setState(true);//預設選取
     
        frm.add(ckb4);
        frm.add(ckb5);
     
        frm.setVisible(true);
     
    }
}


Panel物件:面板。屬於containner子類別。可以做版面配置。
可以放進Frame物件。一個Frame可容納多個Panel
Panel可放button edittext checkbox等componemt





import java.awt.*;

public class PanelTest {
    static Frame frm=new Frame("Panel class");
    static Panel pnl = new Panel(new GridLayout(3,3));
//宣告Panel物件,並帶入layout物件。3x3格的]GridLayout
    static Label lab= new Label("Hello",Label.RIGHT);//標籤文字靠右對齊

    public static void main(String[] args) {
       frm.setLayout(null);//取消Frame版面配置,否則無法正確設定frame內部元件的大小
     
        // frm.setSize(600, 500);
     
        frm.setBounds(300,50, 600, 500);
        frm.setBackground(new Color(0x00ff99));
        frm.setResizable(false);//視窗設為固定大小
   
     
        lab.setBounds(20, 40, 60, 40);
        lab.setBackground(Color.red);

        pnl.setBounds(20, 80, 300, 220);
        pnl.setBackground(Color.GRAY);
        for(int i=1;i<=9;i++){
        pnl.add(new Button(Integer.toString(i)));
     
        }
     
        frm.add(lab);
        frm.add(pnl);
        frm.setVisible(true);
    }
}











2013年4月5日 星期五

不同物件來儲存同一物件、變數


宣告一個bank類別
在main method宣告兩個Rule物件
分別是warrior,wizard
將bank帶入warrior,wizard建構子
這樣warrior wizard儲存同一物件

(應用角色扮演的走地圖與判斷腳色走地圖的位置)

class Bank{
   private  int count=0;
    public  void add(){
    count++;
    }
    public void show(){
    System.out.println(count);
    }
 
}

class Rule{
private Bank bank ;
    Rule(Bank b){
    bank=b;  
    }
public void access(){
bank.add();
}    }


public class accessObj {
     public static void main(String[] args) {
         Bank bank = new Bank();
         Rule warrior = new Rule(bank);
         Rule wizard= new Rule(bank);
         warrior.access();
         wizard.access();
         bank.show();//印出count=2
     }
}