2012년 1월 11일 수요일

AppWidget에서 사용할 수 있는것은?

AppWidget에서 사용할 수 있는 Layout
FrameLayout,
LinearLayout
RelativeLayout.

AppWidget에서 사용할 수 있는 Widget들..
AnalogClock,
Button,
Chromometer,
ImageButton,
ImageView,
ProgressBar
TextView

너무 없죠.. 수수께끼 하는 것도 아니고..
그래도 만들어 볼만한게 AppWidget입니다.

그러나 3.x, 4.x로 넘어가면서 사용할 수 있는게 더 많아 졌다니...

실행중인 Task별 Activity 보기..

1. AndroidManifest.xml에 Permission 처리
    -  <uses-permission android:name="android.permission.GET_TASKS"/>

2. 다음과 같이 코딩을 하세요..
  
    // ActivityManager를 얻고..
   ActivityManager actMgr = (ActivityManager)AppPinScreenLockActivity.this.getSystemService(Activity.ACTIVITY_SERVICE);
   
   
    List<RunningTaskInfo> info = actMgr.getRunningTasks(7);
   
    for (Iterator<RunningTaskInfo> iterator = info.iterator(); iterator.hasNext();)  {
         RunningTaskInfo runningTaskInfo = (RunningTaskInfo) iterator.next();
         Log.d(TAG, "" + runningTaskInfo.topActivity.getClassName());
    }

2012년 1월 7일 토요일

Implementing Dynamic Tab Widget

1. layout xml file (main.xml) 만들기

<?xml version="1.0" encoding="utf-8"?>
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/tabhost" 
    android:layout_height="fill_parent"
    android:layout_width="fill_parent">
     <LinearLayout
         android:layout_width="fill_parent"
         android:layout_height="fill_parent"
         android:orientation="vertical"
         android:padding="5dp">

         <TabWidget
             android:id="@android:id/tabs"
             android:layout_width="fill_parent"
             android:layout_height="wrap_content"/>
          <FrameLayout
             android:id="@android:id/tabcontent"             android:layout_height="wrap_content"
             android:layout_width="fill_parent"
             android:padding="5dp"/>
    </LinearLayout>
</TabHost>
- xml의 계층을 건들지 마시고 각 id의 name은 미리 android에 선언된 이름이므로 바꾸지 말아야 한다.

2. MainActivity 만들기
    - Tab을 만들기 위해서는 우선 TabActivity를 상속받은 Activity를 만들고,  TabHost.TabContentFactory 를 implement해야 한다.

public class TabTestActivity extends TabActivity implements TabHost.TabContentFactory {
          
             .......
       @Override
       public void onCreate(Bundle savedInstanceState) {

           super.onCreate(savedInstanceState);
           // 위에서 만든 main.xml           setContentView(R.layout.main);
           // main.xml 내에 있는 @android:id/tabhost 
           TabHost tabHost = getTabHost();    
       
           // 1. 새로운 tab생성. 물론 생성되는 모든 TabSpec들은 @android:id/tabs 내에 포함되게 됨
           TabHost.TabSpec tabSpec = tabHost.newTabSpec(getString(R.string.str_appranker_tab1));
           // 2. 이부분에서 단순히 String만을 주게 되면 Tab Widget에 String 만 표시된다.

           // 만약, 더 다양한 효과를 주고 싶으면 이부분에 View를 넘기면 된다.
           tabSpec.setIndicator(getString(R.string.str_appranker_tab1));
           // 3. 이부분이 상단 Tab을 눌렀을때 하단에 표시되는 내용부분이다.
           // 직접, View를 넘길수 없으며 Dynamic하게 생성되는 View들을 FrameLayout내에 넣어야 하기에 TabContentFactory를 이용하게 된다.
            tabSpec.setContent(this);
            // 4. TabHost에 생성한 Tab을 넣는다.
            // Tab을 더 생성하고 싶으면 1~4 다시 수행.            tabHost.addTab(tabSpec);
       }

       @Override
       public View createTabContent(String tag) {

           LayoutInflater inflater = getLayoutInflater();
           // Tab을 구별할 수 있는 tag 값에 따라 다른 View를 R.layout.content inflate해서 넣으면 되며, 가장 중요한 것은 @android:id/tabcontent의 하위 view로 rootview를 정의해야한다는것..
           // 그래야 나중에 framelayout에서 보이고 안보이고를 결정해 주죠......
           if(tag.equals(getString(R.string.str_tab1))){
                     return inflater.inflate(R.layout.content, getTabHost().getTabContentView()); 
           }
           return null;
       }
}


-- 근데요.. 하나의 activity내에서 FrameLayout에서 보여주게될 복잡한 view들을 control한다는것은 조금 힘들고 지저분해 보이네요...
-- tabSpec.setContent()에 Intent를 넣어 Activity가 실행되게하여 MVC모델에 충실하게 만드는 것은 어떨런지.....

2012년 1월 2일 월요일

intent-filter의 Grouping..?

안드로이드가 배우기 힘든것은 될것 같은데 안되는 것들이 있고, 이를 극복하기 위해서 참고할 만한 글을 찾기에 너무 힘들고.... 내가 직접 bug-around 해야하고...
안드로이드 개발자에게 직접 묻기도 뭐하고...

암튼, 오늘 찾아 낸 거...

intent-filter도 grouping이 필요하다는 것.. (나만 몰랐나?, 원래 해야하나? 누구든 알면 알려줘여..)

PACKAGE_ 관련 action과 BOOT_COMPLETED, USER_PRESENT는 다른 group으로 묶어야 제대로 동작을 합니다.

말하자면 아래와 같이.... 참고 하세요..

       <receiver android:name=".XXXBootLauncher">
            <intent-filter>
                <action android:name="android.intent.action.PACKAGE_ADDED"/>
                <action android:name="android.intent.action.PACKAGE_REMOVED"/>
                <data android:scheme="package" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
                <action android:name="android.intent.action.USER_PRESENT"/>
            </intent-filter>
        </receiver>

2012년 1월 1일 일요일

Package 삭제 추가에서 PackageName알아내기

등록된 BroadcastReceiver로 Package의 추가 삭제 intent가 전달되는 데요..
packagename은 Uri형태로 전달 됩니다.

즉, package:com.helloaxl.xxx 형태인데요...

이때 packageName을 정확히 얻어 올려면,

intent.getData().getSchemeSpecificPart() 를 호출해야 com.helloaxl.xxx를 얻어 올수 있답니다.

Package 추가 삭제 알아내기

 Manifest 파일에 다음과 같이 receiver를 등록합니다.

<receiver android:name=".XXXReceiver">
   <intent-filter>
     <action android:name="android.intent.action.PACKAGE_ADDED" />
     <action android:name="android.intent.action.PACKAGE_REMOVED" />
     <data android:scheme="package" />
  </intent-filter>
</receiver>

여기서 가장 중요한것은 <data android:scheme="package" />...
빼먹지 마시라는거...