Android: TabActivity Nested Activities

In this tutorial I will show you how to use TabActivity together with ActivityGroup in order to make nested activities inside tabs. In this solution you can have several nested activities on a tab without “loosing” your tab navigation. The idea is to use a LocalActivityManager to start the nested activities. Then replace the View of the ActivityGroup with the view of the different Activities. Now, this may sound complicated, but it’s really quite simple.

First off, the TabActivity class...

원문글 내용 : http://blog.henriklarsentoft.com/2010/07/android-tabactivity-nested-activities/

브로드캐스트리시버의 등록과 해제

[UI Activity...]

    @Override

public void onCreate(Bundle savedInstanceState) {
this.savedInstanceState=savedInstanceState;
        super.onCreate(savedInstanceState);
        
/-* 브로드캐스트리시버 등록 *-
this.registedReceiver =
ReceiverUtil.registerReceiver(this,
"com.test.app.ui.activity.common.ULNetworkReceiver", ConnectivityManager.CONNECTIVITY_ACTION);
}



@Override
protected void onDestroy()
{

super.onDestroy();

/-* 브로드캐스트리시버 해제 *-
if(this.registedReceiver != null) {
ReceiverUtil.unregisterReceiver(this, this.registedReceiver);
}
}


[ReceiverUtil]


public class ReceiverUtil
{
public final static String NETWORK_RECEVIER_CLASS =
                    "com.xxx.xxx.ui.activity.common.ULNetworkReceiver"; // NETWORK RECEVIER 클래스
/-*
 * recevier를 등록한다.
 * @param activity   recevier를 등록할 activity
 * @param recevierName 호출될 BroadcastReceiver 클래스
 * @param recevierEventName recevier event 이름
 * @return BroadcastReceiver
 *-
public static BroadcastReceiver registerReceiver(Activity activity, String recevierName,
String recevierEventName)
{
IntentFilter filter = null;
Class recevierClass = null;
BroadcastReceiver receiver = null;

if(receiver == null)
{
try
{
filter = new IntentFilter(recevierEventName);
recevierClass = Class.forName(recevierName);
receiver = (BroadcastReceiver) recevierClass.newInstance();
activity.registerReceiver(receiver, filter);
Log.d("receiver", "registed BroadcastReceiver...");
}
catch (ClassNotFoundException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IllegalAccessException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (InstantiationException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
finally
{
filter = null;
recevierClass = null;
}
}

return receiver;
}

/-*
 * recevier를 해제한다.
 * @param activity
 * @param receiver
 *-
public static void unregisterReceiver(Activity activity, BroadcastReceiver receiver)
{
if(receiver != null) {
activity.unregisterReceiver(receiver);

Log.d("receiver", "unregisted BroadcastReceiver...");
}
}
}

[ULNetworkReceiver]

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);

/-* 3G, WIFI 둘 중 하나라도 있을 경우 *-
if(activeNetInfo != null && mobNetInfo != null){
String str = "";
if(activeNetInfo.getTypeName().toString().equals("WIFI"))
{
str += "Wi-Fi로 연결중";
}
else if(activeNetInfo.getTypeName().toString().equals("mobile"))
{
str += "3G로 연결합니다. Wi-Fi로 이용 할 수 없습니다.";
}
//Toast.makeText(context, str, Toast.LENGTH_SHORT).show();
}
/-* 3G, WIFI 둘 다 없을 경우 *-
else{
AlertDialog.Builder alert = new AlertDialog.Builder(activity);
alert.setTitle("알림");
alert.setMessage("네트워크 연결불가");
alert.setPositiveButton("확인", new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int which)
{
dialog.dismiss();
activity.onBackPressed();
}
});
alert.show();
}
} catch (Exception e) {

//Log.i("ULNetworkReceiver", e.getMessage());
}
}
}
}


커스텀 타이틀바 처리하기


[클래스]


activity.requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
activity.setContentView(layout);
activity.getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE,
R.layout.common_title_bar);

TextView titleText = (TextView) activity.findViewById(R.id.title_text);
titleText.setText(activity.getString(titleNameId));
titleText.setFadingEdgeLength(0);

LinearLayout ll=(LinearLayout) activity.findViewById(R.id.title_bar);

ViewGroup viewGroup = (ViewGroup)(ll.getParent()).getParent(); //상위레이아웃 객체
viewGroup = (ViewGroup)viewGroup.getChildAt(0);
viewGroup.setPadding(0,0, 0,0); //여백조절



[common_title_bar.xml]


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/title_bar"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    android:gravity="center_vertical"
    android:background="@drawable/title_background"
    >
    <TextView android:id="@+id/title_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:textSize="14.7dip"
        android:textColor="#FFFFFF"
        android:gravity="center_vertical"
        android:paddingLeft="11.3dip"
        />
</LinearLayout>

onConfigurationChanged()이용해서 시스템 세팅 변경에 따른 이벤트 체크하기!!

아래는 서비스 항목의 변경이 일어난 이후, 현재 액티비티를 처리할때에 '시스템 설정에 대한 변경'을 감지하고자 오버라이딩 하는 실제코드의 일부를 보여주고 있다. ActivityGroup을 상속받아야 한다.

@Override

public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
if(mainMstLinear != null ){
mainMstLinear.removeView(tabView);
showTab();
}
}

Configuration 변경시 OnConfigurationChanged 사용하기

아래의 주요 시스템 세팅 변경은 Activity 의 onConfigurationChanged으로 감지가 되어 실시간으로 프로그램이 대응하는 것이 가능합니다.

   orientation: 스크린이 세로에서 가로로 바뀌는 변경사항.
   keyboardHidden: 키보드가 보여지거나 숨겨지는 변경사항 .
   fontScale: 사용자가 원하는 폰트의 크기를 변경하는 것.
   locale: 사용자가 언어 세팅을 변경하는것.
   keyboard: 키보드의 종류가 바뀌는 사항



이를 위해서는 Manifest 파일의 해단 Activity 의 옆에 아래와 같이 android:configChanges 를 먼저 선언합니다.

<activity android:name="RosaryList" android:configChanges="keyboardHidden|orientation"></activity>

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    [ ... Update any UI based on resource values ... ]
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        [ ... React to different orientation ... ]
    }
    if (newConfig.keyboardHidden == Configuration.KEYBOARDHIDDEN_NO) {
        [ ... React to changed keyboard visibility ... ]
    }
}





소스코드에서 안드로이드 버전정보 체크하는 방법

안드로이드 소스코드내에서 버전확인 하는 방법에 대한 검토결과이다.
아래와 같이 android.os.Build 클래스를 사용하여 각 정보를 얻어오는 방법에 대한 샘플이며, 그 결과에 대한 내용



[소스코드]

Log.e("TEST >> ", "Build.VERSION.CODENAME : " +

Build.VERSION.CODENAME.toString() + "");

Log.e("TEST >> ", "Build.VERSION.INCREMENTAL : " + Build.VERSION.INCREMENTAL.toString() + "");

Log.e("TEST >> ", "Build.VERSION.RELEASE : " +

Build.VERSION.RELEASE.toString() + "");

Log.e("TEST >> ", "Build.VERSION.SDK : " + Build.VERSION.SDK.toString() + "");

Log.e("TEST >> ", "Build.VERSION.SDK_INT : " + Build.VERSION.SDK_INT + "");


[실행결과]

02-25 09:21:19.550: ERROR/TEST >>(1084): Build.VERSION.CODENAME : REL

02-25 09:21:19.550: ERROR/TEST >>(1084): Build.VERSION.INCREMENTAL : 43546

02-25 09:21:19.550: ERROR/TEST >>(1084): Build.VERSION.RELEASE : 2.2

02-25 09:21:19.550: ERROR/TEST >>(1084): Build.VERSION.SDK : 8

02-25 09:21:19.550: ERROR/TEST >>(1084): Build.VERSION.CODENAME : REL

02-25 09:21:19.550: ERROR/TEST >>(1084): Build.VERSION.INCREMENTAL : 43546

02-25 09:21:19.550: ERROR/TEST >>(1084): Build.VERSION.RELEASE : 2.2

02-25 09:21:19.550: ERROR/TEST >>(1084): Build.VERSION.SDK : 8

02-25 09:21:19.561: ERROR/TEST >>(1084): Build.VERSION.SDK_INT : 8

02-25 09:21:19.561: ERROR/TEST >>(1084): Build.VERSION.SDK_INT : 8


* Build.VERSION.CODENAME : REL
    ===> 현재의 개발코드네임을 리턴한다. 릴리즈 버전이라면 REL 리턴
* Build.VERSION.INCREMENTAL
    ===> 기본 소스 제어에 의해 사용되는 해당 빌드의 대표하는 내부값
* Build.VERSION.RELEASE
    ===> 사용자에게 보여지는 버전정보
* Build.VERSION.SDK 
    ===> 이 필드는 사용중지되었고, 쉽게 이 정수값을 얻으려면 SDK_INT값을 사용하라고함
* Build.VERSION.SDK_INT
    ===> 사용자에게 보여지는 프레임워크의 SDK 버전, 그것의 유효한 값은 Build.VERSION_CODES에 정의




참고 : http://developer.android.com/reference/android/os/Build.VERSION.html