레이블이 fragment인 게시물을 표시합니다. 모든 게시물 표시
레이블이 fragment인 게시물을 표시합니다. 모든 게시물 표시

2014년 2월 21일 금요일

support v4 library 사용 중 PreferenceFragment를 FragmentPagerAdapter 추가 시 문제점

하위 기기 호환을 위해서 android support v4 library
(http://developer.android.com/tools/support-library/index.html)를 사용하여
fragment들을 사용, 관리하고 있는 중에
preference fragment를 fragmentPagerAdapter에 추가 시 문제가 발생함.

android.support.v4.app.FragmentPagerAdapter 에서는
android.support.v4.app.Fragment 를 처리하고 있어
android.app.Fragment를 상속받은 PreferenceFragment을
v4.appFragment로 처리 할 수 없음.

좀 찾아봤으나 어쩔 수 없이 v13 library를 사용하는 것으로 마무리..
더 찾기도 귀찮음.

http://stackoverflow.com/questions/15845632/adding-preferencefragment-to-fragmentpageradapter

This answer led me to the solution of using the v13 support library, which includes a FragmentPagerAdapter that uses bona-fide android.app.Fragments so it can support the PreferenceFragment.
Assuming you use Eclipse and run the new app wizard with the "Scrollable Tabs + Swipe" Navigation (which gives you the v4 pager boilerplate), here are the modifications you need to make to upgrade to v13:
  • Delete "android-support-v4.jar" file from your libs folder
  • Copy "android-support-v13.jar" from SDK_PATH\extras\android\support\v13; if it's not there, use the SDK manager to install or update "Extras/Android Support Library"
Then, in the Java file:
  • Change FragmentPagerAdapter import from v4 to v13
  • Change FragmentActivity to a plain Activity
  • Change calls to getSupportFragmentManager to getFragmentManager
  • Import all necessary classes from android.app instead of android.support.v4
  • (Except: you still need to use the v4 ViewPager, but it's compatible)
I've copied the modified source below, verified on latest Jellybean.

2013년 7월 3일 수요일

Activity의 Fragment에서 전달한 Intent result 수신 처리

이전 블로그에서 이전 함 (원본 글 2013/07/03 작성)

Activity 내의 Fragment에서 보낸 intent의 requestCode의 값이 좀 달라서 찾다 보니
Fragment에서 전달한 intent의 request code의 값은 좀 다르게 전달 되고 있었음.

일반적인 Activity에서 intent 사용 방법
  public class MyActivity extends Activity {
     ...

     static final int PICK_CONTACT_REQUEST = 0;

     protected boolean onKeyDown(int keyCode, KeyEvent event) {
         if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
             // When the user center presses, let them pick a contact.
             startActivityForResult(
                 new Intent(Intent.ACTION_PICK,
                 new Uri("content://contacts")),
                 PICK_CONTACT_REQUEST);
            return true;
         }
         return false;
     }

     protected void onActivityResult(int requestCode, int resultCode,
             Intent data) {
         if (requestCode == PICK_CONTACT_REQUEST) {
             if (resultCode == RESULT_OK) {
                 // A contact was picked.  Here we will just display it
                 // to the user.
                 startActivity(new Intent(Intent.ACTION_VIEW, data));
             }
         }
     }
 }
 

기존에 Activity에서 사용하던 Intent request code를 사용하려다보니 안되고 0xFFFF 이하의 값을 사용하도록 강제하고 있다.

또한 Fragment에서 Intent를 전송하고 Activity의 onActivityResult 코드에서 전달 받은 requestCode 값이
당초 전달한 값에서 0x40000 이 추가되어 있었음..

찾다보니 Fragment에서 전달한 intent result 처리를 다르게 해줘야 한다는 링크가 있어서

일단 대충 위 링크대로 처리하고 임의로 0x4000을 제거하여 처리했지만.. 왠지 모를 찝찝함..

더 찾다 보니 일본에서 관련 내용을 잘 정리한 링크가 있었음. 이사람 블로그 종종 찾다보면 최신 Android feature에 대해서 잘 정리하고 있는 것 같다...

Fragment에서 전송한 Intent result 처리를 위한 Activity의 onActivityResult 코드
 protected  void onActivityResult ( int requestCode, int resultCode, Intent data) {

    int index = requestCode >> 16 ;
     if (index! = 0 ) {
        index -;
        if (mFragments.mActive == null | | index < 0 | | index> = mFragments.mActive.size ()) {
            Log.w (TAG, "Activity result fragment index out of range : 0x"
                    + Integer.toHexString (requestCode));
            return ;
        }
        Fragment frag = mFragments.mActive.get (index);
        if (frag == null ) {
            Log.w (TAG, "Activity result no fragment exists for index : 0x"
                    + Integer.toHexString (requestCode));
        } else {
            frag.onActivityResult (requestCode & 0xffff , resultCode, data);
        }
        return ;
    }
        
    super . onActivityResult (requestCode, resultCode, data);
}


위 블로그에서 언급한 대로 Fragment의 startActivityForResult를 확인하니 다음과 같다.

이게 중요... 
super.startActivityForResult(intent, ((fragment.mIndex+1)<<16) + (requestCode&0xffff));

GrepCode / com.google.android / android /   4.2.2_r1   / android.app.Fragment
 Call Activity.startActivityForResult(android.content.Intent,int) on the fragment's containing Activity.
    public void startActivityForResult(Intent intentint requestCode) {
        startActivityForResult(intentrequestCodenull);
    }

    
    public void startActivityForResult(Intent intentint requestCodeBundle options) {
        if (mActivity == null) {
            throw new IllegalStateException("Fragment " + this + " not attached to Activity");
        }
        if (options != null) {
            mActivity.startActivityFromFragment(thisintentrequestCodeoptions);
        } else {
            // Note we want to go through this call for compatibility with
            // applications that may have overridden the method.
            mActivity.startActivityFromFragment(thisintentrequestCodeoptions);
        }
    }
    


GrepCode / com.google.android / android /   4.2.2_r1   / android.support.v4.app.FragmentActivity

Modifies the standard behavior to allow results to be delivered to fragments. This imposes a restriction that requestCode be <= 0xffff.
811

812
    @Override
813
    public void startActivityForResult(Intent intentint requestCode) {
814
        if (requestCode != -1 && (requestCode&0xffff0000) != 0) {
815
            throw new IllegalArgumentException("Can only use lower 16 bits for requestCode");
816
        }
817
        super.startActivityForResult(intentrequestCode);
818
    }

    
Called by Fragment.startActivityForResult() to implement its behavior.
822

823
    public void startActivityFromFragment(Fragment fragmentIntent intent
824
            int requestCode) {
825
        if (requestCode == -1) {
826
            super.startActivityForResult(intent, -1);
827
            return;
828
        }
829
        if ((requestCode&0xffff0000) != 0) {
830
            throw new IllegalArgumentException("Can only use lower 16 bits for requestCode");
831
        }
832
        super.startActivityForResult(intent, ((fragment.mIndex+1)<<16) + (requestCode&0xffff));
833
    }
834
    
835
    void invalidateSupportFragment(String who) {
836
        //Log.v(TAG, "invalidateSupportFragment: who=" + who);
837
        if (mAllLoaderManagers != null) {
838
            LoaderManagerImpl lm = mAllLoaderManagers.get(who);
839
            if (lm != null && !lm.mRetaining) {
840
                lm.doDestroy();
841
                mAllLoaderManagers.remove(who);
842
            }
843
        }
844
    }