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" />...
빼먹지 마시라는거...
 

2011년 12월 31일 토요일

logcat option 및 filter 제대로 셋팅하기

1. cmd 실행
2. chcp 65001 실행
3. adb logcat  option filter 실행

-s              Set default filter to silent.
Like specifying filterspec '*:s'
-f <filename>   Log to file. Default to stdout
-r [<kbytes>]   Rotate log every kbytes. (16 if unspecified). Requires -f
-n <count>      Sets max number of rotated logs to <count>, default 4
-v <format>     Sets the log print format, where <format> is one of:

brief process tag thread raw time threadtime long

-c              clear (flush) the entire log and exit
-d              dump the log and then exit (don't block)
-t <count>      print only the most recent <count> lines (implies -d)
-g              get the size of the log's ring buffer and exit
-b <buffer>     request alternate ring buffer
('main' (default), 'radio', 'events')
-B              output the log in binary
<Filter Spec.....>
filterspecs are a series of
<tag>[:priority]

where <tag> is a log component tag (or * for all) and priority is:
V    Verbose
D    Debug
I    Info
W    Warn
E    Error
F    Fatal
S    Silent (supress all output)

<tag>[:priority] 이부분에 대한 설명을 하자면...

public static final String TAG = "HelloAxlActivity"; <---- 이부분에서 선언한 태크
Log.d(TAG, "hello...."); <--- 이렇게 프로그램에서 사용하죠..

adb logcat HelloAxlActivity 가 되는 거죠...

그런데, 이상하죠.. 온동네 tag들이 다나옵니다. 이거 하라는 데로 했는데... 헐...
한가지가 더 있답니다.
마지막으로 젤 중요한것은요... 저도 정말 알고 싶어 했던거...

adb logcat HelloAxlActivity *:S

뒤에 *:S 로 HelloAxlActivity이후 한칸띈 후 마무리를 해주셔야 비로소 HelloAxlActivity Tag만을 가진 로그가 나옵니다. (이거 버근가?)

암튼, priority는 tag이후에 붙여 주시면 되겠습니다.

adb logcat HelloAxlActivity:I *:S  이렇게요...

이것과 똑같이 option을 이용해서 할 수도 있는데요...

adb logcat -s HelloAxlActivity:I

-s 는 silent로 만드는 option입니다.

위와 같이 하면 중간에
--------- beginning of /dev/log/system
.....
--------- beginning of /dev/log/main

이런식으로 두가지의 logfile의 내용을 한꺼번에 보여주는데요..

이는 옵션을 주어 버퍼를 선택할 수 있습니다.
adb logcat -b main -s HelloAxlActivity:I 이런식으로요..

이상이구요. 질문있으시면 알려주세요.