[Android] Parcelable을 이용해 액티비티간 인텐트로 객체넘기기

하루에 한개의 포스트를 업로드 하기도 힘들... (지금도 힘들다) 지만, 오늘 두개째 글을 쓴다.

안드로이드 Parcelable 이라는 인터페이스가 있다.
이놈은 인텐트를 이용해 객체를 넘겨줄때에 써먹을 수가 있는데, 보통은 아래처럼 번들을 이용해 하나씩 꺼내오지만

  Bundle bundle = this.getIntent().getExtras();
  data1 = bundle.getString("TEST1");
  data2 = bundle.getString("TEST2");

객체를 주고받는다면, 좀 더 쉽게 개발을 할수 있을것만 같다!! +_+
이럴때 Parcelable이란놈을 이용한다. 비트맵 형태의 데이터를 주고받는 경우도 가능하리라 생각된다.
일단은 나도 인터넷을 통해 찾아본 자료등을 통해 샘플을 만들어 보았다. 필요한 분들은 참고하기 바란다.

001aa

이미지를 보면 알겠지만, 절대로 샘플코드를 복잡하게 만들지 않는다 -_-
언뜻보면 레이아웃 (main.xml/sub.xml 등)이 좀 복잡해 보일지 모르지만, 입력상자가 몇개있을뿐 복잡할 건 없다.
입력상자 세군데에 데이터를 입력받아 객체를 생성한뒤, 객체를 넘겨주는 식이다.
두번째의 화면에서는 객체를 넘겨받아, 다시 getter 메서드를 이용해 출력해주는 부분이다.

설명을 더이상 할것도 없다.
코드를 보자.

Student.java - 객체(모델)이 되는 클래스
package com.test.vo;

import android.os.Parcel;
import android.os.Parcelable;

/**
 * @author sungsik81
 *
 */
public class Student implements Parcelable {
 public String name;
 public int age;
 public String birthday;
 
 public Student() {
 
 }

 public Student(Parcel in) {
  readFromParcel(in);
 }
 
 public Student(String name, int age, String birthday) {
  this.name = name;
  this.age = age;
  this.birthday = birthday;
 }

 /* (non-Javadoc)
  * @see android.os.Parcelable#describeContents()
  *
  *  Parcel 하려는 오브젝트의 종류를 정의한다.
  *  어떤 특별한 객체를 포함하고 있는지에 대한 설명을 리턴값으로 표현 하는 것이라고 보면된다.
  *  bit mask 형식의 integer를 리턴 하며,값을 체크 할 때 bit mask 체크를 해서 어떤 것들이 들어 있는지 알 수 있다.
  */
 @Override
 public int describeContents() {
  return 0;
 }
 
 /* (non-Javadoc)
  * @see android.os.Parcelable#writeToParcel(android.os.Parcel, int)
  *
  * Parcel에 데이터를 쓰는 부분.
  */
 @Override
 public void writeToParcel(Parcel dest, int flags) {
  dest.writeString(name);
  dest.writeInt(age);
  dest.writeString(birthday);
 }

 private void readFromParcel(Parcel in) {
  name = in.readString();
  age = in.readInt();
  birthday = in.readString();
 }
 
 /**
  * @author sungsik81
  *
  * Parcelable.Creator<T> 클래스는 createFromParcel() 과 newArray() 메소스가 필요하다.
  * Parcel로 부터 값을 읽어 오기 위해서는 Parcelable.Creator Interface 가 필요하다.
  */
 public static final Parcelable.Creator<Student> CREATOR = new Parcelable.Creator() {

  //writeToParcel() 메소드에서 썼던 순서대로 읽어 오는 것입니다.
  @Override
  public Object createFromParcel(Parcel source) {
   return new Student(source);
  }

  @Override
  public Object[] newArray(int size) {
   return new Student[size];
  }
 
 };

 /*
  * 이하, Getter/Setter
  */
 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public int getAge() {
  return age;
 }

 public void setAge(int age) {
  this.age = age;
 }

 public String getBirthday() {
  return birthday;
 }

 public void setBirthday(String birthday) {
  this.birthday = birthday;
 }
}

MainActivity.java

package com.test;

import com.test.vo.Student;

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

public class MainActivity extends Activity {
 Button submitButton;
 EditText myTextView;
 EditText myAge;
 EditText myBirthday;
 String myText;
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
        myTextView = (EditText) findViewById(R.id.myName);
        myAge = (EditText) findViewById(R.id.myAge);
        myBirthday = (EditText) findViewById(R.id.myBirthday);

        submitButton = (Button) findViewById(R.id.ok);
        submitButton.setOnClickListener(new OnClickListener(){

        String inputMyName;
        int inputMyAge;
        String inputMyBirthday;
         
        Student student = null;
       
   @Override
   public void onClick(View v) {
          inputMyName = myTextView.getText().toString();
          inputMyAge = Integer.valueOf(myAge.getText().toString());
          inputMyBirthday = myBirthday.getText().toString();
 
          student = new Student(inputMyName, inputMyAge, inputMyBirthday);
         
    Intent intent = new Intent(MainActivity.this, SubActivity.class);
    intent.putExtra("STUDENT", student);
    startActivity(intent);
   }
         
        });
    }
}

SubActivity.java

package com.test;

import com.test.vo.Student;

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

public class SubActivity extends Activity {
 Button backBtn;
 Bundle bundle;
 TextView resultMyNameTextView;
 TextView resultMyAgeTextView;
 TextView resultMyBirthdayTextView;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.sub);
       
        bundle = this.getIntent().getExtras();
  Student student = bundle.getParcelable("STUDENT");
       
  resultMyNameTextView = (TextView) findViewById(R.id.resultMyName);
  resultMyAgeTextView = (TextView) findViewById(R.id.resultMyAge);
  resultMyBirthdayTextView = (TextView) findViewById(R.id.resultMyBirthday);
 
  resultMyNameTextView.setText(student.getName());
  resultMyAgeTextView.setText(String.valueOf(student.getAge()));
  resultMyBirthdayTextView.setText(student.getBirthday());
 
        backBtn = (Button) findViewById(R.id.back);
        backBtn.setOnClickListener(new OnClickListener(){

   @Override
   public void onClick(View v) {
    onBackPressed();
   }
         
        });
 }

}

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <LinearLayout
     android:orientation="horizontal"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     >
     <TextView
   android:layout_width="150dip"
   android:layout_height="wrap_content"
   android:text="name : "  
   />
  <EditText
   android:id="@+id/myName"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   android:text="sungsik"
   />
 </LinearLayout>
    <LinearLayout
     android:orientation="horizontal"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     >
     <TextView
   android:layout_width="150dip"
   android:layout_height="wrap_content"
   android:text="age : "  
   />
  <EditText
   android:id="@+id/myAge"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   android:text="30"
   />
 </LinearLayout>
    <LinearLayout
     android:orientation="horizontal"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     >
     <TextView
   android:layout_width="150dip"
   android:layout_height="wrap_content"
   android:text="birthday : "  
   />
  <EditText
   android:id="@+id/myBirthday"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   android:text="0810"
   />
 </LinearLayout>  
 <Button
  android:id="@+id/ok"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:text="Submit To SubActivity"
  />
</LinearLayout>


sub.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <LinearLayout
     android:orientation="horizontal"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     >
     <TextView
   android:layout_width="150dip"
   android:layout_height="wrap_content"
   android:text="name : "  
   />
  <TextView
   android:id="@+id/resultMyName"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   />
 </LinearLayout>
    <LinearLayout
     android:orientation="horizontal"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     >
     <TextView
   android:layout_width="150dip"
   android:layout_height="wrap_content"
   android:text="age : "  
   />
  <TextView
   android:id="@+id/resultMyAge"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   />
 </LinearLayout>
    <LinearLayout
     android:orientation="horizontal"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     >
     <TextView
   android:layout_width="150dip"
   android:layout_height="wrap_content"
   android:text="birthday : "  
   />
  <TextView
   android:id="@+id/resultMyBirthday"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   />
 </LinearLayout>  
 <Button
  android:id="@+id/back"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:text="Submit To SubActivity"
  />  
</LinearLayout>


AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.test"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".MainActivity" android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".SubActivity" android:label="@string/app_name" />
    </application>
    <uses-sdk android:minSdkVersion="7" />
</manifest>

[Android] Wifi 다루기

* Android Manifest.xml수정
Wifi를 사용하기 위해서는 아래 두 permission이 추가되어야 함
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />

* 현재 supplicant의 정보 얻기
WifiManager wm = (WifiManager)getSystemService(Context.WIFI_SERVICE);
WifiInfo wi = wm.getConnectionInfo();

Log.d("WIFI", "BSSID : " + wi.getBSSID());
Log.d("WIFI", "Hidden SSID : " + wi.getHiddenSSID());
Log.d("WIFI", "IP : " + wi.getIpAddress());
Log.d("WIFI", "LinkSpeed : " + wi.getLinkSpeed());
Log.d("WIFI", "MAC Addr. : " + wi.getMacAddress());
Log.d("WIFI", "Net ID : " + wi.getNetworkId());
Log.d("WIFI", "RSSI : " + wi.getRssi());
Log.d("WIFI", "SSID : " + wi.getSSID());
Log.d("WIFI", "Supplicant State : " + wi.getSupplicantState());
Log.d("WIFI", "Detailed State : " + WifiInfo.getDetailedStateOf(wi.getSupplicantState()));
Log.d("WIFI", "String : " + wi.toString());
Log.d("WIFI", "Ping Result : " + wm.pingSupplicant());

// Wifi가 연결되었는지 상태 체크
DetailedState ni_ds = WifiInfo.getDetailedStateOf(wi.getSupplicantState());

if ((wi.getIpAddress()!= 0)
       && (ni_ds == DetailedState.CONNECTED || ni_ds == DetailedState.OBTAINING_IPADDR)){
         // Wifi AP에 연결된 상태
}


출처:Wifi 다루기
http://icess.egloos.com/3339065

[Android] BroadcastReceiver에서 wifi / 3G 분기하기

public class ULNetworkReceiver extends BroadcastReceiver {
    private Activity activity;
    
    public ULNetworkReceiver() {
        super();
    }

    public ULNetworkReceiver(Activity activity) {
        this.activity = activity;
    }
    
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        
        // 네트웍에 변경이 일어났을때 발생하는 부분
        if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
            try {
                ConnectivityManager connectivityManager =
                        (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
                NetworkInfo activeNetInfo = connectivityManager.getActiveNetworkInfo();
                NetworkInfo mobNetInfo =
                        connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
                
                WifiManager wifiManager =
                        (WifiManager) activity.getSystemService(Context.WIFI_SERVICE);
                WifiInfo wifiInfo = wifiManager.getConnectionInfo();

                if(wifiInfo != null) {

                    /** WIFI 활성화 했고, AP 사용가능 */
                    if(wifiInfo.getIpAddress()>0 && wifiInfo.getSSID()!=null
                               && wifiInfo.getSupplicantState().toString().equals("COMPLETED")) {

                    }
                    
                    /** WIFI 활성화 했지만, AP 사용불가 */
                    else if(wifiInfo.getIpAddress()==0&&wifiInfo.getSSID()==null
                            && (!wifiInfo.getSupplicantState().toString().equals("UNINITIALIZED")
                                    || wifiInfo.getSupplicantState().toString().equals("INACTIVE")
                                    || wifiInfo.getSupplicantState().toString().equals("SCANNING"))) {
                        Log.e("net info >>> ", "wifi use / AP not use ...");
                        
                    }
                    
                    /** WIFI 설정을 활성화 하지않은 경우/ 3G 사용가능할때 */
                    else if(activeNetInfo!=null && activeNetInfo.getTypeName().equals("mobile") &&
                            (wifiInfo.getSupplicantState().toString().equals("UNINITIALIZED")
                                    || wifiInfo.getSupplicantState().toString().equals("SCANNING")
                                    || wifiInfo.getSupplicantState().toString().equals("INACTIVE") )) {
                        Log.e("net info >>> ", "wifi not use / 3G success ...");
                        
                    }
                    /** 3G, WIFI 둘 다 없을 경우 */
                    else {
                        Log.e("getSupplicantState >>> ", wifiInfo.getSupplicantState().toString()+"...");
                    }        
                }
            } catch (Exception e){

            }            
        }
    }
}

진저브레드관련 - Android App 개발시 주의사항요청(CTS 승인이슈건)

폰에서 디버깅을 하려고 할 때 아래와 같은 메세지가 나오며 디버깅이 되지 않는다면 AndroidManifest.xml 파일내 <application> 태그내에 디버깅이 가능하다고 선언을 해 두어야 한다.

[2010-03-04 10:23:27 - XX]Device '040376670B006008' requires that applications explicitely declare themselves as debuggable in their manifest.
[2010-03-04 10:23:27 - XX]Application 'com.vtron.subway' does not have the attribute 'debuggable' set to TRUE in its manifest and cannot be debugged.

<application android:icon="@drawable/icon"
             android:label="@string/app_name" android:debuggable="true">
그런데, 이것이 진저브레드와 관련이 있는 부분이기에 내용을 공유하기 위해 포스팅을 한다.


오늘 안드로이드 생강빵(쿠키) 버전이 발표되었습니다.
이에 구글 CTS 상에 주의사항이 있어 보내드립니다.

오늘부터 적용되는 CTS 항목중에 AndroidManifest.xml에 debuggable이 true된 내역을 확인하는 항목이 있습니다
debuggable="true"로 되어 있으면 CTS pass가 안됩니다.
debuggable="false"로 하거나 없도록 해서 배포해 주셔야 합니다.

SKT 서비스 어플 배포시 꼭 챙겨주세요. 다른 사람들에게도 공유해 주시구요.
빌드시 debuggable 속성에 대해서는 아래 링크 참조하십시오.

http://developer.android.com/intl/zh-CN/sdk/eclipse-adt.html

출처:진저브레드관련 - Android App 개발시 주의사항요청(CTS 승인이슈건)

[안드로이드] Disable scroll view action

Disable scroll view action

어플리케이션을 개발하다보니, 경우에 따라 스크롤의 사용유무를 달리 처리해야 하는 경우가 생긴다.
하나의 레이아웃이고, 스크롤뷰로 감싸여 있는 구조라면 아래의 코드를 사용해 보기 바란다.

// Get the ScrollView
final ScrollView myScroll = (ScrollView) findViewById(R.id.display_scrollview);

// Disable Scrolling by setting up an OnTouchListener to do nothing
myScroll.setOnTouchListener( new OnTouchListener(){
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        return true;
    }
});

// Enable Scrolling by removing the OnTouchListner
tvDisplayScroll.setOnTouchListener(null);   


출처 : http://stackoverflow.com/questions/2229178/disable-scroll-view-action