------

[ AD ] Port Monitor ( Try to use a Best WebSite Monitoring Tool )

------

android:allowTaskReparenting 친화력 있는 태스크 설정 애트리뷰트이다. 이 애트리뷰트가 설정되지 않으면 <application>엘리먼트의 allowTaskReparenting에 설정된 값이 액티비티에 적용된다.
디폴트 값은
false이다.


an
droid:alwaysRetainTaskState
사용자가 Task를 오랫동안 방치하면 시스템은 Root Activity를 제외한 모든 Activities의 Task를 Clear 시킨다. 이 애트리뷰트가 true로 설정 되어 있다면 Task는 오랜 시간이 지나도 Stack에 있는 모든 Activity를 유지한다.
디폴트 값은
false이다.

android:clearTaskOnLaunch 이 속성이 true로 설정되어 있으면 사용자가 Task를 떠났다가 다시 돌아 올 때마다 Stack은 Root Activity로 정리된다.
디폴트 값은
false이다.


A
ndroid:configChanges
시스템은 각 어플리케이션을 종료하고 재시작한 뒤 리소스 값을 다시 읽어 들임으로써 언어, 위치, 하드웨어에 대한 런타임 변경을 지원한다. 런타임 구성 변경을 감지하는 activity를 가지려면 Manifest 노드에 android: configChanges 속성을 추가 한 뒤 변경을 하고자 하는 구성 변경을 지정한다. 여러 값을 사용할 때는 |’에 의해 구분된다.

android:launchMode – 액티비티가 어떻게 런치되어야 하는지에 대한 명령이다.

4가지 런치모드(“standard” “singleTop” “singleTask” “singleInstance” )가 있고 디폴트는 “standard”이다.

모드는 두개의 main Group으로 나뉜다(standard, singleTop / singleTask, singleInstance).
standard”, “singleTop”모드를 가지는 액티비티는 여러 번 인스턴스화 될 수 있으나(Intent Object가 “FLAG_ACTIVITY_NEW_TASK” flag를 가지고 있지 않을 경우에 해당)

singleInstance” 액티비티는 하나의 Task만 시작 할 수 있다.
 
standard” vs “singleTop” :
standard” 액티비티에 대한 새로운 Intent가 발생하면 언제나 해당 Class의 Instance가 만들어 지지만
 “singleTop” 액티비티의 새로운 Instance는 생성 될 수도 있다. 즉, Target Task에 이미 해당 액티비티의 인스턴스가 존재하면 새로 만들어지지 않고 기존 인스턴스가 새로운 Intent를 받게 된다.
 
singleTask” vs “singleInstance” :
singleTask” 액티비티는 다른 액티비티들이 해당 Task의 일부가 되는 것을 허락하여 “singleTask” 액티비티는
액티비티 스택의 root에 존재하게 되고 다른 액티비티들은 동일한 Task에서 시작 될 수 있다.
 이와 달리 “singleInstance” 액티비티는 어떤 다른 액티비티들도 해당 Task의 일부가 될 수 없다.
이로 인해 해당 Task에는 유일한 Activity만 존재하고 또 다른 Activity를 실행하려고 하면 새로운 Task로 할당이 된다.

'온라인게임' 카테고리의 다른 글

홈 버튼이 마지막 액티비티를 재시작 안할때...  (0) 2010.10.18
Activity Tag  (0) 2010.10.18
AlertDialog Builder에서  (0) 2010.10.18
DLNA (Digital Living Network Alliance )  (0) 2010.10.14
애플리케이션 서명하기  (0) 2010.10.14

삼성 갤럭시 s 에서 나온 문제.... 또 버그버그 ... .지겨운 삼성 갤럭시 s 버그 버그 버그

( HTC Desire에서는 안나온 문제..)




new AlertDialog.Builder(mContext)
  .setSingleChoiceItems( R.array.local, 
    mSelect,
   new DialogInterface.OnClickListener() {
    public void onClick(DialogInterface dialog, int which) {
     mSelect = which;
    }
   }
  )
 
  .setPositiveButton("확인", new DialogInterface.OnClickListener() {
   public void onClick(DialogInterface dialog, int which) {
    
    String[] locals = getResources().getStringArray(R.array.local);
    if ( mSelect != 0 ) 
     mTextViewLocal.setText(locals[mSelect]);
    else
     mTextViewLocal.setText("");
    

   }
  }).show



정상적으로 나오게 할려면,....
new AlertDialog.Builder(mContext)
  .setTitle("지역")
  .setSingleChoiceItems( R.array.local, 
    mSelect,
   new DialogInterface.OnClickListener() {
    public void onClick(DialogInterface dialog, int which) {
     mSelect = which;
    }
   }
  )
 
  .setPositiveButton("확인", new DialogInterface.OnClickListener() {
   public void onClick(DialogInterface dialog, int which) {
    
    String[] locals = getResources().getStringArray(R.array.local);
    if ( mSelect != 0 ) 
     mTextViewLocal.setText(locals[mSelect]);
    else
     mTextViewLocal.setText("");
  
   }
  }).show


'온라인게임' 카테고리의 다른 글

Activity Tag  (0) 2010.10.18
android:launchMode  (0) 2010.10.18
DLNA (Digital Living Network Alliance )  (0) 2010.10.14
애플리케이션 서명하기  (0) 2010.10.14
리스트 구분 헤더 추가 / Separating Lists with Headers  (3) 2010.10.14
DLNA (Digital Living Network Alliance )certification 이란
DLNA 인증이란 뜻입니다
DLNA (Digital Living Network Alliance )는 세계 홈네트워크 상용화를 선도해나갈
공식협력업체로 여기서 발표한 내용은
가전제품이나 PC 또는 무선기기간의 유,무선 홈네트워크를 통하여
서로 다른 브랜드간 제품들과콘텐츠를 공유할수 있는 설계를 제공하는것이라 했습니다

그래서 이 가이드라인에 따라 만든 제품들은 서로 음악,사진 비디오 영상물등의
콘텐츠를 네트워크를 통해 공유할수 있다는것입니다
다시말하면 DLNA 인증을 받은 제품들 끼리는 유선이나 무선으로 홈네트워크를 통해
미디어 내용들을 서로 주고 받을수 있다는것을 의미합니다

요즘 브랜드가 다르면 형식이 달라서 상호간 플레이가 안된다거나 하는데
그러지않고 서로 호환이 가능할수 있다는 의미도 되겠지요

'온라인게임' 카테고리의 다른 글

android:launchMode  (0) 2010.10.18
AlertDialog Builder에서  (0) 2010.10.18
애플리케이션 서명하기  (0) 2010.10.14
리스트 구분 헤더 추가 / Separating Lists with Headers  (3) 2010.10.14
List Separator Text View Style  (0) 2010.10.14

안드로이드 마켓에 배포를 하기 위해서는 애플리케이션에 서명을 해주어야 한다. 자신이 인증하는 애플리케이션임을 서명을 통해서 알리는 것이다.

그러기 위해서는 개인 키를 포함하는 암호화된 서명 파일이 있는 keystore가 필요하고 이를 JDK에서 제공하는 jarsigner 로 공개키로 서명하게 된다.

이클립스에서 Android SDK를 통해서 애플리케이션을 실행할 때마다 자동으로 디버그 서명을 만들고 이 서명이 애플리케이션이 사용될 때마다 서명되기 때문에 눈에 보이지는 않지만 항상 애플리케이션을 서명되고 있다.

  • 디버그 서명 위치: ~/.android/debug.keystore

 

개인 인증서의 효용

본인이 개발한 애플리케이션임을 알리고 관리를 위해서는 가능하면 하나의 인증서로 관리하는 것이 편리할 것이다.

  • 업그레이드 간편화
  • 여러 애플리케이션을 하나의 프로세스로 실행
  • 코드, 데이터 공유

 

서명 인증서 만들기

JDK에서 제공하는 keytool로 공개키와 개인키 쌍을 만들 수 있다. 이 키 쌍은 keystore에 저장되며 이 keystore를 통해 접근이 가능하다.

http://java.sun.com/j2se/1.5.0/docs/tooldocs/#security 참조

 

keytool 사용

 

key store 생성
  1. keytool -genkey -v -keystore myandroid.keystore -alias mykeystore -keyalg RSA -validity 10000

 

  1. keystore 암호를 입력하십시오:  <---- 키 저장소에 접근 할 수 있는 암호
  2. 새 암호를 다시 입력하십시오:
    이름과 성을 입력하십시오.
      [Unknown]:  Gangtai goh
    조직 단위 이름을 입력하십시오.
      [Unknown]:  self
    조직 이름을 입력하십시오.
      [Unknown]:  Go for Android
    구/군/시 이름을 입력하십시오?
      [Unknown]:  SEOUL
    시/도 이름을 입력하십시오.
      [Unknown]: 
    이 조직의 두 자리 국가 코드를 입력하십시오.
      [Unknown]:  KO
    CN=Gangtai goh, OU=self, O=Go for Android, L=SEOUL, ST=Unknown, C=KO이(가) 맞습니까?
      [아니오]:  예

    다음에 대해 유효 기간이 10,000일인 1,024비트 RSA 키 쌍 및 자체 서명된 인증서(SHA1withRSA) 생성 중
        : CN=Gangtai goh, OU=self, O=Go for Android, L=SEOUL, ST=Unknown, C=KO
    <gtkokeystore>에 대한 키 암호를 입력하십시오.
        (keystore 암호와 같은 경우 Enter를 누르십시오): 
    [gtko.keystore 저장 중]

 

키 쌍을 만들며 myandroid.keystore에 저장() 며 이 키는 mykeystore 라는 이름으로 접근이 가능하다. 키를 만드는 알고리즘은 RSA이고 10000일(27년)간 유효하다.

 

finger print 확인

keytool -list 로 SDK의 인증서의 MD5 지문을 확인 할 수 있다.

 

  1. keytool -list -alias mykeystore -keystore myandroid.keystore
    keystore 암호를 입력하십시오: 
    gtkokeystore, 2009. 10. 22, PrivateKeyEntry,
    인증서 지문(MD5): AF:FE:77:FA:3D:F9:28:FB:AC:86:92:6E:E3:A9:9C:66

 

adb install

android debug bridge 로 android device에 apk를 설치할 수 있다.

 

에러: Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES]

apk 에 sign이 안되서 그런다.

 

 

 

애플리케이션 서명

 

1_ 먼저 서명이 안된 애플리케이션(.apk)를 만든다: Eclipse에서 프로젝트 선택후 컨텍스트 메뉴(오른쪽 마우스 클릭)에서 Android Tools -> Export Unsigned Application Package..

2_ 개인키 저장소에 있는 키(비밀키)로 서명한다

  1. jarsigner -verbos -keystore mykey.keystore Myandroid.apk mykeyalias

 

Eclipse 에서 signed application package

 

1) Project Context menu -> Android Tools -> Export Signed Applicaiton package

개인키가 저장된 keystore 를 선택한다.

keystore에 저장된 alias 를 선택하고 keypass를 넣는다.

최종 application package 를 선택한다.

 

adb install 로 설치

  1. $ adb install -l MJAndroid.apk
        pkg: /data/local/tmp/MJAndroid.apk
    Success

 

실패시 - 서명 안된 application package 설치시

  1.     pkg: /data/local/tmp/MJAndroid.apk
    Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES]

 

 

디버그 인증서로 sign후 설치시

    pkg: /data/local/tmp/MJAndroid.apk

Failure [INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES]

 

 

참조

 

참조

debug 인증서 관리

keytool -list 로 SDK의 디버그 인증서의 MD5 지문을 확인 할 수 있다.

  1.  keytool -list -alias androiddebugkey -keystore ~/.android/debug.keystore -storepass android -keypass android
    androiddebugkey, 2009. 6. 4, PrivateKeyEntry,
    인증서 지문(MD5): 4E:6F:03:A9:70:C9:A1:A1:FE:19:F5:0C:6B:2F:77:D8
  • 디버그 서명 인증서는 생성후 365일간 유효하다

 

debug 인증서 변경

Windows > Preferences > Android > Build

 

구글 맵 API 키 받기

 

개인 서명 인증서 혹은 디버그 인증서의 지문(MD5)이 준비되었으면 구글 API 키를 요청할 수 있다.

API 키는 인증서와 동일한 서명을 한 애플리케이션에서만 사용할 수 있다.

이클립스에서 Android SDK를 통해서 애플리케이션을 실행할 때마다 자동으로 디버그 서명을 만들고 이 서명이 애플리케이션이 사용될 때마다 서명되기 때문에 눈에 보이지는 않지만 항상 애플리케이션을 서명되고 있다.

  • 디버그 서명 위치: ~/.android/debug.keystore

 

 

 

debug 인증서 관리

keytool -list 로 SDK의 디버그 인증서의 MD5 지문을 확인 할 수 있다.

  1.  keytool -list -alias androiddebugkey -keystore ~/.android/debug.keystore -storepass android -keypass android
    androiddebugkey, 2009. 6. 4, PrivateKeyEntry,
    인증서 지문(MD5): 4E:6F:03:A9:70:C9:A1:A1:FE:19:F5:0C:6B:2F:77:D8
  • 디버그 서명 인증서는 생성후 365일간 유효하다

 

debug 인증서 변경

Windows > Preferences > Android > Build

 

애플리케이션 서명과 구글API 키 인증 시나리오

keytool로 키 쌍을 생성하면 사용자 홈 디렉토리의 특정한 곳에 keystore로서 저장된다. 비밀 키는 키 저장소에 암호화 되어 보호되며 이 비밀 키로 애플리케이션을 서명하게 된다. - 특정 조직의 경우 공인 인증서 이용 -

구글 API를 이용하려면 API용 키가 필요한데 이 때 인증 서명서의 finger print(MD5)가 필요하다

안드로이드는 공개 키를 이용하여 서명 인증서를 해독하여 사용하는데 애플리케이션이 설치 될 때만 서명 인증서를 검사하기 때문에 설치 후에는 인증서나 키가 만료되도 실행이 가능하다.

 

절차

  1. 서명서의 MD5 finger print
  2. http://code.google.com/android/maps-api-signup.html 에 finger print를 붙이고 해당 서명서의 Map API 키를 발급 받는다

    1. 구글 계정이 없어도 발급이 가능하다
  3. Map API 키를 복사해서 Map activity의 레이아웃 파일에 apiKey의 값으로 입력한다.
    아래는 MapView의 예제

 

  1. <com.google.android.maps.MapView
            android:id="@+id/mapmain"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:clickable="true"
            android:apiKey="0P18K0TAE0dO06EiSAFV3K85OJrH6cC1uqSIEYg"
        />

 

MD5 finger print

아래는 디버그 키의 핑거 프린트를 보여준다.

  1.  keytool -list -alias androiddebugkey -keystore ~/.android/debug.keystore

'온라인게임' 카테고리의 다른 글

AlertDialog Builder에서  (0) 2010.10.18
DLNA (Digital Living Network Alliance )  (0) 2010.10.14
리스트 구분 헤더 추가 / Separating Lists with Headers  (3) 2010.10.14
List Separator Text View Style  (0) 2010.10.14
iostream  (0) 2010.10.14

Layout/XML 구성
1.구분자 헤더
   
  

2.단순 리스트
   
  

3.복합 리스트
   
   
       
       
  


하나의 Interface로 여러개의 영역 제공하는 SeparatedListAdapter addSection()를 사용한 후에 child영역을 만든다. Now let’s create the actual SeparatedListAdapter class which provides a single interface to multiple sections of other Adapters. After using addSection() to construct the child sections, you can easily use ListView.setAdapter() to present the now-separated list to users. As for the Adapter internals, to correctly find the selected item among the child Adapters, we walk through subtracting from the original position until we find either a header (position = 0) or item in the current child Adapter (position < size). 어댑터 클래스 / SeparatedListAdapter
public class SeparatedListAdapter extends BaseAdapter {  
public final Map sections = new LinkedHashMap();   
    public final ArrayAdapter headers;   
    public final static int TYPE_SECTION_HEADER = 0;   
   
    public SeparatedListAdapter(Context context) {   
        headers = new ArrayAdapter(context, R.layout.list_header);   
    }   
   
    public void addSection(String section, Adapter adapter) {   
        this.headers.add(section);   
        this.sections.put(section, adapter);   
    }   
   
    public Object getItem(int position) {   
        for(Object section : this.sections.keySet()) {   
            Adapter adapter = sections.get(section);   
            int size = adapter.getCount() + 1;   
   
            // check if position inside this section   
            if(position == 0) return section;   
            if(position < size) return adapter.getItem(position - 1);   
   
            // otherwise jump into next section   
            position -= size;   
        }   
        return null;   
    }   
   
    public int getCount() {   
        // total together all sections, plus one for each section header   
        int total = 0;   
        for(Adapter adapter : this.sections.values())   
            total += adapter.getCount() + 1;   
        return total;   
    }   
   
    public int getViewTypeCount() {   
        // assume that headers count as one, then total all sections   
        int total = 1;   
        for(Adapter adapter : this.sections.values())   
            total += adapter.getViewTypeCount();   
        return total;   
    }   
   
    public int getItemViewType(int position) {   
        int type = 1;   
        for(Object section : this.sections.keySet()) {   
            Adapter adapter = sections.get(section);   
            int size = adapter.getCount() + 1;   
   
            // check if position inside this section   
            if(position == 0) return TYPE_SECTION_HEADER;   
            if(position < size) return type + adapter.getItemViewType(position - 1);   
   
            // otherwise jump into next section   
            position -= size;   
            type += adapter.getViewTypeCount();   
        }   
        return -1;   
    }   
   
    public boolean areAllItemsSelectable() {   
        return false;   
    }   
   
    public boolean isEnabled(int position) {   
        return (getItemViewType(position) != TYPE_SECTION_HEADER);   
    }   
   
    @Override   
    public View getView(int position, View convertView, ViewGroup parent) {   
        int sectionnum = 0;   
        for(Object section : this.sections.keySet()) {   
            Adapter adapter = sections.get(section);   
            int size = adapter.getCount() + 1;   
   
            // check if position inside this section   
            if(position == 0) return headers.getView(sectionnum, convertView, parent);   
            if(position < size) return adapter.getView(position - 1, convertView, parent);   
   
            // otherwise jump into next section   
            position -= size;   
            sectionnum++;   
        }   
        return null;   
    }   
   
    @Override   
    public long getItemId(int position) {   
        return position;   
    }   
   
}  


As expected, it correctly prevents the section headers from being selected, and seamlessly stiches together the various Adapters. This approach also uses convertView correctly as long as the child Adapters return getItemViewType() and getViewTypeCount() normally. No special changes are needed for an Adapter to become a child. Now let’s use SeparatedListAdapter in some example code. We use the XML layouts defined earlier to create an ArrayAdapter and an advanced two-row SimpleAdapter, and then add both as sections to our SeparatedListAdapter.
실제 적용 샘플 Activity
public class ListSample extends Activity {   
   
    public final static String ITEM_TITLE = "title";   
    public final static String ITEM_CAPTION = "caption";   
   
    public Map createItem(String title, String caption) {   
        Map item = new HashMap();   
        item.put(ITEM_TITLE, title);   
        item.put(ITEM_CAPTION, caption);   
        return item;   
    }   
   
    @Override   
    public void onCreate(Bundle icicle) {   
        super.onCreate(icicle);   
   
        List> security = new LinkedList>();   
        security.add(createItem("Remember passwords", "Save usernames and passwords for Web sites"));   
        security.add(createItem("Clear passwords", "Save usernames and passwords for Web sites"));   
        security.add(createItem("Show security warnings", "Show warning if there is a problem with a site's security"));   
   
        // create our list and custom adapter   
        SeparatedListAdapter adapter = new SeparatedListAdapter(this);   
        adapter.addSection("Array test", new ArrayAdapter(this,   
            R.layout.list_item, new String[] { "First item", "Item two" }));   
        adapter.addSection("Security", new SimpleAdapter(this, security, R.layout.list_complex,   
            new String[] { ITEM_TITLE, ITEM_CAPTION }, new int[] { R.id.list_complex_title, R.id.list_complex_caption }));   
   
        ListView list = new ListView(this);   
        list.setAdapter(adapter);   
        this.setContentView(list);   
   
    }   
   
}  


resulting interface behaves just like the browser preferences list, and you could easily create other custom Adapters to insert into the various sections, such as including icons or checkboxes. (아이콘/체크박스)

'온라인게임' 카테고리의 다른 글

DLNA (Digital Living Network Alliance )  (0) 2010.10.14
애플리케이션 서명하기  (0) 2010.10.14
List Separator Text View Style  (0) 2010.10.14
iostream  (0) 2010.10.14
stdafx / std a fx / Standard Application Freamworks / MFC  (0) 2010.10.14
안드로이드 리스트에 구분자 줄을 추가 하기

상단에 TabHost, TabWidget , TabContent는 설명에서 제외하고..

 

일단 리스트뷰에서만 설명하면.. ListView




레이아웃 XML 문서에서


        
 


와 같이 리스트 위에 텍스트 뷰를 추가 한것 뿐..
public class GetProvidersTrue extends ListActivity {
 
 Context context;
 private ArrayList list;
 private ArrayAdapter adapter;
 LocationManager locationManager;
 List providers;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.list);
        context = this;
        list = new ArrayList ();
        
        locationManager = (LocationManager)this.getSystemService(LOCATION_SERVICE);
        providers = locationManager.getAllProviders();
        //list = new ArrayList();
        //list.add("테스트1");
        //list.add("테스트2");
        //.add("테스트3");

        
        //list.add("[작동하는 지리정보 제공자]");
        TextView tv = (TextView)findViewById(R.id.tv);
        tv.setText("[작동하는 지리정보 제공자]");
        providers = locationManager.getProviders(true);
        for ( int i = 0; i < providers.size(); i++)
        {
         list.add( providers.get(i));
        }

        adapter = new ArrayAdapter
          (this,android.R.layout.simple_list_item_1, list);
        
        setListAdapter(adapter);
    }
    protected void onListItemClick(ListView l, View v, int position, long id) 
    {
     super.onListItemClick(l, v, position, id);
     
     Toast.makeText(context, v.toString(), Toast.LENGTH_LONG);
     
    }
}




visual studio .net 2003에서는

#include <iostream.h>가
#include <iostream>으로 바뀌어서 예전 버전과 구별합니다.

iostream.h 화일은 없고 iostream 화일만 있습니다.
visual studio .net 2003이 깔린 include 폴더에는 많은 헤더 화일들이 있는데
이 폴더에서 직접확인 하실 수 있습니다.

iostream.h 헤더 화일은 일반 화일과 같이 iostream 화일로 바뀌었습니다.
이렇게 .h를 생략하고 쓰는 헤더화일이 몇개 됩니다.

stdafxStandard Application Freamworks 의 약자로 개발자들의 생산성 향상을 위해 
MS 에서 제공하는 소프트웨어 라이브러리 체계를 뜻하며,  MFC 로 구성되어 있다. 

참고로 많이 사용되는 application framework 로는 .NET Framework( Windows 계열 ),  Cocoa ( Objective C / Mac OS X), Swing (Java) 등이 있다.

그럼 Precompiled header (미리 컴파일된 헤더. 여기에서는 precompiled header 로 통일) 란 무엇인가...

C / C++ 언어에서 헤더 파일은 C 전처리기(preprocessor) 에 의해 자동적으로 소스 코드를 포함하게 된다.

그런데 일부 헤더 파일의 경우 방대한 크기의 소스 코드를 포함할 수 있고( 예를 들면 window.h),
이런 코드들을 매번 컴파일하면 컴파일 시간이 매우 길어지게 된다.

그래서 자주 바뀌지 않는 기본적인 라이브러리들의 경우에 컴파일 시간을 줄이고자
컴파일러가 사전에 헤더 파일들을 미리 컴파일 해 놓고 쓸 수 있게 하고 있다.

이렇게 컴파일 시간을 줄이기 위해 사전에 컴파일한 결과물이 VC 의 경우 pch(precompiled header) 라는 확장자 명으로 저장된다. 비주얼 스튜디어의 솔루션 폴더에 생기는 프로젝트명.pch 가 바로 그것이다.

precompiled header 를 사용할 경우 precompiled header 로 지정한 헤더 파일 및 소스 코드는 컴파일시에 컴파일 되지 않고 pch 의 결과물을 가져다 사용하게 되는 것이다.


stdafx.h 가 포함하는 정보는 무엇들인가요? 


자주 사용되는 공용 소스들을 precompiled header 로 만들어 제공



stdafx.h 에 포함하는 내용들을 살펴보면 윈도우 객체 생성에 필요한
기본 클래스 (afx.h / afxwin.h 등),  
윈도우 컨트롤( afxctl.h / afxcmn.h 등),
기본 DB 관련 클래스 ( afxdb.h / afxdao.h ),
네트워크 관련 클래스 ( afxsock.h ) 등등 기본적인 프레임워크 구축에 필요한
필수 헤더들이 포함되어 있다.




stdafx.h 에 어떤 내용을 넣으면 되나요 

앞서 말했듯이 stdafx.h 는 한번만 미리 빌드해 놓고 그 다음부터는 재빌드 안하고 쓰는 모듈들이 되야 하므로, 
precompiled header 인 stdafx.h 에는프로젝트 진행 중에 거의 값이 바뀌지 않는 외부 라이브러리나 전역 변수 등의 내용을
포함시키면 된다.
이들을 pch 로 만들어 놓고 빌드하면 매번 재빌드 하지 않고 컴파일 시간을 많이 줄일 수 있다.

참고로, GCC ( .gch ) ,  C++ Builder ( vcl.h ) 등에서도 precompiled header 를 지원한다.




에러 : fatal error C1010: unexpected end of file while looking for precompiled header directive
미리 컴파일된 헤더 지시문을 찾는 동안 예기치 않은 파일의 끝이 나타났습니다
( 혹은 버전에 따라 "Did you forget to add '#include "stdafx.h"' to your source?" 라는 문구가 표시되기도 함 )

해결방안 :  precompiled header 를 사용하도록 설정된 상태에서 컴파일을 하였는데 precompiled header 를 찾지 못했다는 의미.
보통 해당 소스코드에 stdafx.h 가 인클루드 되어 있지 않거나, stdafx.h 의 위치가 잘못 되어 있어서 발생한다.  
stdafx.h 를 소스코드의 가장 위쪽에서 include 하도록 해 주면 된다. 
혹은 precompiled header 가 잘못 세팅되어 찾지 못하는 문제일수도 있다. precompiled header 를 사용 안함으로 체크하여 pch 를 현재 소스 코드에 맞게 재 생성을 해 준다.

에러 : fatal error C1853: "Debug/test.pch" is not a precompiled header file created with this compiler

해결방안 :  현재 소스 코드에서 사용할 수 있는 pch 와 버전이 맞지 않는다는 의미.
precompiled header 를 사용 안함으로 체크하여 pch 를 현재 소스 코드에 맞게 재 생성을 해 준다.


홈키 눌렀을때 로그를 찍어보니
01-02 03:07:19.389: DEBUG/[debug](2469): _onSaveInstanceState
01-02 03:07:19.389: DEBUG/[debug](2469): _onPause
01-02 03:07:19.413: DEBUG/[debug](2469): _onWindowFocusChanged
01-02 03:07:19.600: DEBUG/[debug](2469): _surfaceDestroyed
01-02 03:07:19.889: DEBUG/[debug](2469): _onStop
홈버튼 길게 눌러 복귀시엔
01-02 03:08:37.022: DEBUG/[debug](2469): _onStart
01-02 03:08:37.022: DEBUG/[debug](2469): _onResume
01-02 03:08:37.038: DEBUG/[debug](2469): _surfaceCreated
01-02 03:08:37.038: DEBUG/[debug](2469): _surfaceChanged
01-02 03:08:37.569: DEBUG/[debug](2469): _onWindowFocusChanged
요래 찍히는 군요

제가 사용하는 코드입니다.
surfaceDestroyed시에 join으로 스레드를 종료시키고
다시 surfaceCreated 될 때 새로 스래드를 생성해서 실행해줍니다.


@Override
public void surfaceDestroyed(SurfaceHolder holder) {
 if(LOG_FLAG) Log.d("[debug]", "_surfaceDestroyed");
 boolean retry = true;

  thread.setRunning(false);
  while (retry) {
   try {
    thread.join();
    retry = false;
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
  }
 }
@Override
 public void surfaceCreated(SurfaceHolder holder) {
  if(LOG_FLAG) Log.d("[debug]", "_surfaceCreated");
 
  if(thread.getState() == Thread.State.TERMINATED) {
   thread = new MingleThread();
   thread.setRunning(true);
   thread.start();
  }else{
   thread.setRunning(true);
   thread.start();
  }
 }
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
 if(LOG_FLAG) Log.d("[debug]", "_surfaceDestroyed");
 boolean retry = true;

  thread.setRunning(false);
  while (retry) {
   try {
    thread.join();
    retry = false;
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
  }
 }

@Override
 public void surfaceCreated(SurfaceHolder holder) {
  if(LOG_FLAG) Log.d("[debug]", "_surfaceCreated");
  
  if(thread.getState() == Thread.State.TERMINATED) {
   thread = new MingleThread();
   thread.setRunning(true);
   thread.start();
  }else{
   thread.setRunning(true);
   thread.start();
  }
 }

Thread 제어
class MingleThread extends Thread{
  @Override
  public void run() {
     while (mRun) {
        .....
   }
  }
  
  public void setRunning(boolean b) {
   mRun = b;
  }
 }
http://www.androidpub.com/861068

+ Recent posts