2012-09-28

Android 小程式 : Activity 之間的資料傳遞

當應用程式需要將資料由一個 Activity 傳送給另一個 Activity 時,該怎麼做呢 ? 我藉由下面這個『定點 PO 圖』的小程式來示範並稍微解說一下。假設這個專案 (Project) 的名稱為 : Practice2

程式功能 :
在主畫面的兩個 EditText 欄位中分別輸入座標值 X 與 Y,按『執行』鈕後,將預設的小圖示顯示在指定的座標位置上。


程式運作簡略說明 :
我們要由 MainActivity 中把座標資料傳給 SecondActivity,然後再由 SecondActivity 接收到座標資料後透過 DrawBitMap 將小圖示顯示出來。我們要借助 Intent 與 Bundle 這兩個物件來達到 Activity 之間資料傳送的目的。


特別注意幾個重點 :

1 . 在 AndroidManifest.xml 中加入第二個 Activity 的名稱敘述
為了讓第二個 Activity 能正常運做,還必須在 AndroidManifest.xml 定義檔中加入第二個 Activity 的名稱 (此範例為 SecondActivity),敘述的位置要放在 <application> ... </ application> 之中,請參考下方 AndroidManifest.xml 定義檔 : Practice2/AndroidManifest.xml 中的紅色字體。留意這行敘述的 .SecondActivity 前方的點 " . " 千萬不要漏掉了 !  android:name=".SecondActivity" 那個點 "." 的意義你可以想成是放置在 package="a.b.c" 包裹之中的意思,其全名可表示為 a.b.c.SecondActivity 由於定義檔開頭已經明確宣告 package="a.b.c",所以可以只用 "." 來表示 Activity 所放置的位置就是在 "a.b.c" package 之中。(package 的名稱請依照您自己為 Project 所設定的為準)

2 . 使用 Intent 與 Bundle 來傳送資料
重點請參考下方程式碼中以紅色字體標示的部份,已加上註解說明,這邊我就不再贅述囉 !


PS : 程式中並沒有對超出座標範圍的資料做進一步的處理,有興趣者請自行加上。



佈局檔 : Practice2/res/layout/activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world"
        android:textAppearance="?android:attr/textAppearanceSmall"
        android:textSize="22sp"
        tools:context=".MainActivity" />

    <EditText
        android:id="@+id/editText1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/editText2"
        android:layout_alignParentRight="true"
        android:layout_marginTop="50dp"
        android:ems="10"
        android:inputType="number" >
        <requestFocus />
    </EditText>

    <EditText
        android:id="@+id/editText2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_below="@+id/editText1"
        android:layout_toRightOf="@+id/textView1"
        android:ems="10"
        android:inputType="number" />

    <Button
        android:id="@+id/btn_start"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/editText2"
        android:layout_below="@+id/editText2"
        android:text="@string/make_sure" />

    <Button
        android:id="@+id/btn_end"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/btn_start"
        android:layout_alignBottom="@+id/btn_start"
        android:layout_alignParentRight="true"
        android:text="@string/end" />

    <TextView
        android:id="@+id/textView3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/editText2"
        android:layout_alignBottom="@+id/editText2"
        android:text="@string/location_y"
        android:textSize="25sp" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/editText1"
        android:layout_alignBottom="@+id/editText1"
        android:layout_alignParentLeft="true"
        android:text="@string/location_x"
        android:textSize="25sp" />

</RelativeLayout>



字串資源檔 : Practice2/res/values/strings.xml
<resources>
    <string name="app_name">定點PO圖</string>
    <string name="hello_world">指定座標並顯示圖片</string>
    <string name="menu_settings">Settings</string>
    <string name="title_activity_main">定點PO圖</string>
    <string name="make_sure">執行</string>
    <string name="end">結束</string> 
    <string name="location_x">請輸入 X 座標</string>
    <string name="location_y">請輸入 Y 座標</string>
</resources>



AndroidManifest 定義檔 : Practice2/AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="a.b.c"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="15" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >

        <activity
            android:name=".MainActivity"
            android:label="@string/title_activity_main" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity 
            android:name=".SecondActivity" 
            android:label="@string/app_name" >
        </activity>

    </application>
</manifest>





Java 程式碼的部份 :

(MainActivity) : Practice2/src/a/b/c/MainActivity.java
package a.b.c;

import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;

public class MainActivity extends Activity implements OnClickListener {

    Button btn_start, btn_end;
    EditText editText1, editText2;
    int x,y;
  
    @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        WidgetSetting();  //設定元件
    }

    

    private void WidgetSetting() {

        btn_start = (Button)findViewById(R.id.btn_start);
        btn_end = (Button)findViewById(R.id.btn_end);
        editText1 = (EditText)findViewById(R.id.editText1);
        editText2 = (EditText)findViewById(R.id.editText2);
       
        //設定兩個按鈕的監聽
        btn_start.setOnClickListener(this);
        btn_end.setOnClickListener(this);
    }
   
    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub

        //利用元件的 Id 來判別是哪個按鈕被按下了
        switch(v.getId()) {
             case R.id.btn_start:  //執行鈕被按下
                 TransferData();   //進行資料傳送
                 break;
            case R.id.btn_end:    //結束鈕被按下
                finish();         //直接結束
                break;
        }
    }
   
    private void TransferData() {
        //按下 [執行] 鈕進行傳送資料的程序
        //判斷兩個輸入欄位是否有資料輸入
        //若無輸入則給予 0
        //這是一種偷懶的做法 XD
        //攔截到錯誤時就給予 0 數值
        //若有輸入則把兩個輸入欄位的資料
        //轉換成數值後再指定給 x,y

        try {        
            x = (int)Integer.parseInt(editText1.getText().toString());
        } catch (Exception e) {
            x = 0;
        }
        try {
            y = (int)Integer.parseInt(editText2.getText().toString());
        } catch (Exception e) {
            y = 0;
        }
     
        //透過 Bundle 夾帶資料並隨著 Intent 
        //傳送到下一個 Activity 的 4 個步驟
     
        //1. 宣告 Intent 並指定去向
        //由 MainActivity 傳到 SecondActivity 
        Intent intent = new Intent();
        intent.setClass(MainActivity.this, SecondActivity.class);

       
        //2. 利用  Bundle 物件來夾帶資料
        Bundle bundle = new Bundle();

      
        //LOCATION_X(Y) 為識別字, x 為資料(值)
        //接收方可透過識別字來提取資料(值)  

        bundle.putInt("LOCATION_X", x); 
        bundle.putInt("LOCATION_Y", y); 

      
        //3. 接著利用 intent 的 putExtras 方法
        //將 bundle 物件附加到 intent 上
        intent.putExtras(bundle);

        
        //4. 傳送到下一個 Activity
        startActivity(intent);
    }
}


(SecondActivity) : Practice2/src/a/b/c/SecondActivity.java
package a.b.c;

import android.app.Activity;
import android.os.Bundle;

//第二個 Activity
public class SecondActivity extends Activity {

    int X,Y;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub

        super.onCreate(savedInstanceState);
        setContentView(new DrawBitMap(this));

        //接收並處理 MainActivity 傳過來的資料 
        ReceiveXY();  
    }
   
    private void ReceiveXY() {
        //接收由 MainActivity 傳過來的資料
        Bundle bundle = this.getIntent().getExtras();

        //透過識別字將值取出
        this.X = bundle.getInt("LOCATION_X");  
        this.Y = bundle.getInt("LOCATION_Y");
    }
}



(DrawBitMap) : Practice2/src/a/b/c/DrawBitMap.java
package a.b.c;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.MotionEvent;
import android.view.View;

//這個 DrawBitMap 類別主要是用來顯示圖片
public class DrawBitMap extends View {

    SecondActivity activity;
    Bitmap bp;
    Paint paint;
   
    //建構子
    public DrawBitMap(Context context) {

        super(context);
        //引用 SecondActivity
        this.activity = (SecondActivity)context;
       
        paint = new Paint();
        paint.setColor(Color.WHITE);
        paint.setTextSize(25);

        //指定圖檔
        bp = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
    }
   
    @Override
    protected void onDraw(Canvas canvas) {
        // TODO Auto-generated method stub

        super.onDraw(canvas);
        canvas.drawColor(Color.BLACK);
        canvas.drawText("座標 X : " + activity.X, 5, 30, paint);
        canvas.drawText("座標 y : " + activity.Y, 5, 55, paint);
        canvas.drawText("碰觸螢幕回到上一頁", 5, 100,paint);
    
        //依照座標將圖 PO 出來
        canvas.drawBitmap(bp, activity.X, activity.Y, null);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // TODO Auto-generated method stub

        if (event.getAction() == MotionEvent.ACTION_DOWN){
            //碰觸螢幕結束 SecondActivity 程序
            activity.finish();
        }
        return true;
    }
}

4 則留言:

  1. 您好
    我想請問如果xy座標要用藍芽得到的座標來移動,那我在xy座標要如何更改定義?

    回覆刪除
    回覆
    1. 您好 ^_^
      由於本人還未涉足『藍牙』這方面的應用,所以無法提供任何意見給您。
      只能提供 Android Reference 相關連結,請自行由 API 中尋找您要的資訊。
      http://developer.android.com/reference/android/bluetooth/package-summary.html

      未能直接解惑,尚請海涵

      刪除
    2. 您好

      請問如果我只是想單純的接收並顯示圖示座標的話,只需要作SecondActivity和DrawBitMap?
      而我的座標是透過電腦來的,這樣的話還是需要用到Intent和Bundle嗎?

      不知道是否能跟您要個電子信箱,能跟您說明我的目前的問題(因為用圖示解釋比較清楚XD)

      這是我的電子信箱:andy9873212000@yahoo.com.tw
      希望能收到您的回覆或回信

      刪除
    3. 已經透過您的 Email 寄信給您了 ~
      願聞其詳 ~ 但不一定能幫上忙
      請多包涵

      刪除

搜尋此網誌