프로그래밍/안드로이드 앱

009. Examples - 예제 리스트를 보여주고 실행하는 구조만들기

산을좋아한라쯔 2013. 12. 17. 15:09
반응형

안드로이드의 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