안드로이드의 API 예제를 실행해보면, 처음 화면에 여러 package리스트가 보이고, 그 중 하나를 누르면 그 package밑에 실행할 수 있는 Activity들을 선택할 수 있는 구조로 되어 있다. 한 프로젝트에, 여러 샘플들 혹은 실행할 수 있는 Activity를 두고 선택하게끔하는 구조로 훌륭하게 사용될 수 있게다.
이번에는, 이 API예제에서 사용된, 자동으로 package들과 그 밑에 있는 Activity들을 검색해서 리스트로 만들어주고, 선택하면 실행될 수 있게해주는 구조를 만들어 보겠다.
1. 새 프로젝트 만들기
- Eclipse에서 File - New - Other...해서 'Android Application Project' 선택
- Application Name : Android_MyExamples
Package Name: com.myexamples - 나머지는 Default값으로 놔둔다.
2. activity_main.xml 삭제
기본으로 생성된 res/layout/activity_main.xml을 삭제한다.
3. MainActivity.java 수정
기본으로 생성된 MainActivity.java를 아래 내용과 같이 수정한다.
package com.myexamples; import java.text.Collator; import java.util.*; import android.os.Bundle; import android.app.ListActivity; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.view.View; import android.widget.ListView; import android.widget.SimpleAdapter; public class MainActivity extends ListActivity { String samplePackagePath = "com.myexamples.Path"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Intent intent = getIntent(); String path = intent.getStringExtra(samplePackagePath); if (path == null) { path = ""; } setListAdapter(new SimpleAdapter(this, getData(path), android.R.layout.simple_list_item_1, new String[] { "title" }, new int[] { android.R.id.text1 })); getListView().setTextFilterEnabled(true); } protected List<Map<String, Object>> getData(String prefix) { List<Map<String, Object>> myData = new ArrayList<Map<String, Object>>(); Intent mainIntent = new Intent(Intent.ACTION_MAIN, null); mainIntent.addCategory(Intent.CATEGORY_SAMPLE_CODE); PackageManager pm = getPackageManager(); List<ResolveInfo> list = pm.queryIntentActivities(mainIntent, 0); if (null == list) return myData; String[] prefixPath; String prefixWithSlash = prefix; if (prefix.equals("")) { prefixPath = null; } else { prefixPath = prefix.split("/"); prefixWithSlash = prefix + "/"; } int len = list.size(); Map<String, Boolean> entries = new HashMap<String, Boolean>(); for (int i = 0; i < len; i++) { ResolveInfo info = list.get(i); CharSequence labelSeq = info.loadLabel(pm); String label = labelSeq != null ? labelSeq.toString() : info.activityInfo.name; if (prefixWithSlash.length() == 0 || label.startsWith(prefixWithSlash)) { String[] labelPath = label.split("/"); String nextLabel = prefixPath == null ? labelPath[0] : labelPath[prefixPath.length]; if ((prefixPath != null ? prefixPath.length : 0) == labelPath.length - 1) { addItem(myData, nextLabel, activityIntent( info.activityInfo.applicationInfo.packageName, info.activityInfo.name)); } else { if (entries.get(nextLabel) == null) { addItem(myData, nextLabel, browseIntent(prefix.equals("") ? nextLabel : prefix + "/" + nextLabel)); entries.put(nextLabel, true); } } } } Collections.sort(myData, sDisplayNameComparator); return myData; } private final static Comparator<Map<String, Object>> sDisplayNameComparator = new Comparator<Map<String, Object>>() { private final Collator collator = Collator.getInstance(); public int compare(Map<String, Object> map1, Map<String, Object> map2) { return collator.compare(map1.get("title"), map2.get("title")); } }; protected Intent activityIntent(String pkg, String componentName) { Intent result = new Intent(); result.setClassName(pkg, componentName); return result; } protected Intent browseIntent(String path) { Intent result = new Intent(); result.setClass(this, MainActivity.class); result.putExtra(samplePackagePath, path); return result; } protected void addItem(List<Map<String, Object>> data, String name, Intent intent) { Map<String, Object> temp = new HashMap<String, Object>(); temp.put("title", name); temp.put("intent", intent); data.add(temp); } @Override @SuppressWarnings("unchecked") protected void onListItemClick(ListView l, View v, int position, long id) { Map<String, Object> map = (Map<String, Object>)l.getItemAtPosition(position); Intent intent = (Intent) map.get("intent"); startActivity(intent); } }
이 소스는 Android예제의 API demos에서 참조한 것이고, 달라진 부분은 두 군데이다.
- onCreate()의 intent.getStringExtra()와 browseIntent()의 putExtra()에서 package이름을 "com.myexamples.Path"
만약 다른 package들을 리스트에 나타내기 위해서는 이 부분을 수정해서 사용하면 되겠다. - browseIntent()에서 setClass()하는 부분을, 현 Activity클래스 이름인 "MainActivity.class"로 지정
만약 클래스 이름을 다른 것으로 했다면, 이 부분을 MainActivity가 아닌 다른 이름으로 지정하면 되겠다.
소스는 간단한 구조인데, getData()메서드를 통해서 package들을 읽어서 List로 만들고, 이 List를 ListActivity의 View로 보여주는 구조이다.
(세부내용을 파악하려고 많은 시간을 투자할 필요 없이, 그냥 라이브러리처럼 사용해도 무방할 듯하다)
이것으로 com.myexamples.Path밑에 있는 package들을 List에 로드해서 보여줄 수 있는 구조가 완성되었다. 그러나 이 상태에서 Run하면 리스트에 아무것도 안나올 것이다. 왜냐면 아직 com.myexamples밑에 package가 하나도 없기 때문이다.
이제 package하나와 그 밑에 Activity클래스 하나를 만들어서, List에 뜨도록 해보겠다. (앞에서 만들었던 ActivityList예제의 소스를 사용하도록 하겠다.)
4. 서브 프로그램 만들기
List에 표출되는 것은 com.myexamples로 시작되는 package와 그 밑에 있는 실행가능한 Activity들이다. 이 서브 프로그램을 만드는 것을 요약하면, 다음과 같은 작업을 수행하는 것이라 할 수 있다.
- 서브 프로그램이 들어갈 package 만들기
- Manifest파일에 서브 프로그램의 Activity 삽입
- View 만들기
- Activity 만들기
차례대로 만들어보기로 하자.
서브 프로그램이 들어갈 package 만들기
List에 표출되는 package는 com.myexamples로 시작되야 한다. 여기서는, com.myexamples.listactivity라는 package를 만들도록 하자.
- Package Explorer에서 src를 선택하고 마우스 우클릭. New-Package를 누르고, Name에 com.myexamples.listactivity를 타이핑하고 Finish버튼 누른다.
Manifest파일에 서브 프로그램의 Activity 삽입
AndroidManifest.xml파일을 열어서 서브프로그램에서 사용될 Activity를 삽입하도록 한다.
잠시 후 만들 서브프로그램의 Activity클래스 이름은 ListActivityTest이다. 따라서 Manifest파일에서 application항목에 아래와 같은 activity항목을 넣는다.
<activity android:name=".listactivity.ListActivityTest" android:label="listactivity/ListActivityTest"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.SAMPLE_CODE" /> </intent-filter> </activity>
여기서 android:label에 할당한 listactivity/ListActivityTest가 앱을 구동했을 때 리스트에 나타나는 문자가 된다. 즉, listactivity가 첫번째 레벨이 되고, 이 listactivity가 선택되면 그 다음 레벨인 ListActivityTest가 보이게 된다.
View 만들기
- res/laylut을 선택하고 마우스 우클릭. New-Other해서 Android/Android XML Layout File 선택하고 'Next'버튼
- File:listactivitytest_view, Root Element로 LinearLayout 선택하고 'Finish'버튼
- listactivitytest_view.xml파일을 아래내용이 되도록 수정
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:id="@+id/output" android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="#758AA7" android:padding="1px" android:text="Click" android:textColor="#ffffff" /> <ListView android:id="@+id/@android:list" android:layout_width="match_parent" android:layout_height="wrap_content" > </ListView> </LinearLayout>
위 xml을 Graphical Layout으로 보면 다음과 같다.
Activity 만들기
- Package Explorer에서 com.myexamples.listactivity패키지를 선택하고 마우스 우클릭. New-Class한 후, Name에 ListActivityTest를 타이핑하고 Finish
- ListActivityTest.java파일의 내용을 아래와 같이 되도록 수정
package com.myexamples.listactivity; import com.myexamples.R; import android.os.Bundle; import android.app.ListActivity; import android.view.View; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.TextView; public class ListActivityTest extends ListActivity{ TextView content; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.listactivitytest_view); content = (TextView)findViewById(R.id.output); String[] values = {"Item0","Item1","Item2","Item3"}; //ArrayAdapter(Context context, int resource, T[] objects) //ArrayAdapter설명: // http://developer.android.com/reference/android/widget/ArrayAdapter.html ArrayAdapter<String> adapter = new ArrayAdapter<String> (this,android.R.layout.simple_list_item_1,values); //assign adapter to List setListAdapter(adapter); } //List의 item을 클릭하면, position과 string이 textView에 표출되게. @Override protected void onListItemClick(ListView l, View v, int position, long id){ super.onListItemClick(l, v, position, id); String itemValue = (String)l.getItemAtPosition(position); content.setText("Clicked Position: "+position+"\n"+"Clicked item: "+itemValue); } }
소스에서 주의할 점은 다음과 같다. - com.myexamples.R을 import
- onCreate()에서 setContentView에 View로 만든 listactivitytest_view를 지정
이제 Run을 할 수 있는 상태로 완성되었다.
지금까지 했으면 프로젝트는, com.myexamples패키지에 MainActivity.java, com.myexamples.listactivity패키지에 ListActivity Test.java가 있겠고, res/layout에 listactivitytest_view.xml이, 그리고 androidManifest.xml이 수정되어 있겠다.
5. Run
- Package Explorer에서 Android_MyExamples프로젝트를 선택하고 마우스 우클릭
- Run As - Run Configurations...선택하고, 왼쪽 위 부근에 있는 "New launch configuration" 툴 아이콘 클릭
- Name: MyExamples로 하고, Browse버튼을 눌러 Android_MyExamples프로젝트 선택
- Target탭을 눌러 "Always prompt to pick device"를 체크
- 나머지는 전부 디폴트값으로 놔두고, Apply버튼 누른 후, Run
Run을 하면 아래 그림과 같이 서브프로그램의 Activity인 ListActivityTest의 label이름(listactivity/ListActivityTest) 중 첫 레벨인 listactivity가 보이고, 이 listactivity를 누르면 ListActivityTest가 표출되고, ListActivityTest를 누르면 이 Activity가 실행된다.
-끝-
'프로그래밍 > 안드로이드 앱 ' 카테고리의 다른 글
008. Example - ListActivity (0) | 2013.12.16 |
---|---|
007. Game - 두더지잡기 (0) | 2013.12.16 |
006. Example04_SurfaceView (0) | 2013.11.12 |
005. Example03_Canvas (0) | 2013.11.12 |
004. Example02_Activity와 화면이동 (0) | 2013.11.11 |