KS blog

killins.egloos.com

포토로그



Shraing Content by KillinS

  - 앱들간의 콘텐츠 송수신은 Intent API와 ActionProvider 오브젝트를 이용

1. 콘텐츠 송신


  - Intent를 만들 때 그 Intent가 어떤 action을 유발(trigger)할 지를 결정

  - ACTION_SEND : 다른 앱에 데이터를 전달하기 위한 Intent를 선언

  - 송신 : 데이터, 데이터형을 명시하면 시스템이 대상 앱의 목록을 띄우거나, 대상 앱으로 바로 송신(대상 앱이 하나일 경우)

  - 수신 : manifest 파일에 수신받을 수 있는 데이터형 명시


1) 텍스트 콘텐츠 송신

  - 예제

    Intent sendIntent = new Intent();
    sendIntent.setAction(Intent.ACTION_SEND);
    sendIntent.putExtra(Intent.EXTRA_TEXT, "my text");
    sendIntent.setType("text/plain");
    startActivity(sendIntent);

  - Intent.createChooser() : 기본 연결 앱을 정하더라도 항상 chooser를 실행. 맞는 앱 없으면 시스템메시지 출력. 제목 출력가능

    Intent sendIntent = new Intent();
    sendIntent.setAction(Intent.ACTION_SEND);
    sendIntent.putExtra(Intent.EXTRA_TEXT, "my text");
    sendIntent.setType("text/plain");
    startActivity(Intent.createChooser(sendIntent, getResources().getText(R.string.send_to));

  - 몇몇 표준 엑스트라들(EXTRA_EMAIL, EXTRA_CC, EXTRA_SUBJECT 등)을 set할 수도 있지만, 수신 앱이 해당 엑스트라를 수신하지 않으면 의미가 없음


2) 바이너리 콘텐츠 송신

  - 적절한 MIME 타입, URI, 그리고 EXTRA_STREAM 엑스트라를 이용하여 바이너리 데이터 송신. 보통 이미지에 사용

    Intent shareIntent = new Intent();
    shareIntent.setAction(Intent.ACTION_SEND);
    shareIntent.putExtra(Intent.EXTRA_STREAM, uriToImage);
    shareIntent.setType("image/jpeg");
    startActivity(Intent.createChooser(shareIntent, getResources().getText(R.string.send_to));

  - MIME 타입 "*-*"는 generic data stream 만을 수신하는 앱에서만 사용 가능

  - 콘텐츠 수신 앱은 해당 Uri에 대한 퍼미션 필요. 해결방법은,

    1) external/shared 스토리지에 파일로 쓰고 Uri.fromFile()로 Uri 생성.
    2) MODE_WORLD_READABLE 모드로 openFileOutput()으로 얻어온 앱 디렉토리에 getFileStreamPath()로 얻어온 File사용
        Uri.fromFile()로 Uri 생성
    3) 그림 등 미디어 파일은 시스템의 MediaStore에 scanFile()을 이용해서 저장되고 읽을 수 있다.
        onScanCompleted()로 Uri 생성
    4) 이미지는 insertImage()로 시스템의 MediaStore에 저장될 수 있고, 이 메소드는 uri를 리턴
    5) 앱 고유의 ContentProvider에 데이터를 저장. 퍼미션 확인해야 함


3) 복수개의 콘텐츠 송신

  - ACTION_SEND_MULTIPLE 액션, Intent#putParcelableArrayListExtra() 메소드 이용

  - 콘텐츠들의 종류에 따라 MIME 타입을 잘 설정해야 함

    ArrayList<Uri> imageUris = new ArrayList<Uri>();
    imageUris.add(imageUri1);
    imageUris.add(imageUri2);
    Intent shareIntent = new Intent();
    shareIntent.setAction(Intent.ACTION_SEND_MULTIPLE);
    shareIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, imageUris);
    shareIntent.setType("image/-");
    startActivity(Intent.createChooser(shareIntent, "share images to..."));



2. 콘텐츠 수신
 
1) Manifest 수정

  - <intent-filter> 엘리먼트로 어떤 콘텐츠를 수신할 지 설정

    <activity android:name=".ui.MyActivity">
      <intent-filter>
        <action android:name="android.intent.action.SEND_MULTIPLE" />
        <category android:name="android.intent.category.DEFAULT" />
        <ata android:mimeType="image/-" />
      </intent-filter>
      <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.DEFAULT" />
        <ata android:mimeType="text/plain" />
      </intent-filter>
    </activity>


2) 수신 컨텐츠의 사용

  - getIntent() 메소드로 Intent 오브젝트 수신

  - onCreate()는 다른 앱 뿐만 아니라 런처에 의해 호출될 수도 있으므로 intent 사용전에 확인할 것

    void onCreate(Bundle savedInstanceState) {
      Intent intent = getIntent();
      String action = intent.getAction();
      String type = intent.getType();
      if (Intent.ACTION_SEND.equals(action) && type != null) {
        if ("text/plain".equals(type)) {
          handleSendText(intent);
        } else if (type.startsWith("image/")) {
          handleSendImage(intent);
        }
      } else if (Intent.ACTION_SEND_MULTIPLE.equals(action) && type != null) {
        if (type.startsWith("image/") {
          handleSendMultipleImages(intent);
        }
      }
    }
    void handleSendText(Intent intent) {
      String text = intent.getStringExtra(Intent.EXTRA_TEXT);
      ...
    }



3. Share Action 추가

  - 안드로이드 4.0(API leven 14)에서부터 ActionProvider를 통한 ActionBar에 앱을 추가하는 기능을 구현

  - ShareActionProvider : 공유 intent만 제공하면 이것이 알아서 나머지를 다 수행함

1) 메뉴 선언 업데이트

  - ShareActionProviders를 이용하려면, menu resource 파일의 <item>에 android:actionProviderClass 애트리뷰트를 추가
    <menu xmlns:android="http://schemas.android.com/apk/res/android">
      <item android:id="@id/menu_item_share"
        android:showAsAction="ifRoom"
        android:title="Share"
        android:actionProviderClass="android.widget.ShareActionProvider"" />
   </menu>

  - 아이템의 표시 및 기능은 ShareActionProvider에 위임하지만, 무엇을 share하고자 하는지는 provider에 알려줘야 함

2) Share Intent 선언

  - ShareActionProvider에 무엇을 share 할 지 알려주어야 함
    1) MenuItem에서 관련된 아이템을 찾음
    2) MenuItem.getActionProvider() 메소드를 콜하여 ShareActionProvider 인스턴스를 얻음
    3) share intent를 업데이트 하기 위해 ShareActionProvider#setShareIntent() 메소드를 콜

    private ShareActionProvider mShareActionProvider;
    ...

   @Override
   public boolean onCreateOptionsMenu(Menu menu) {
       // Inflate menu resource file.
       getMenuInflater().inflate(R.menu.share_menu, menu);

       // Locate MenuItem with ShareActionProvider
       MenuItem item = menu.findItem(R.id.menu_item_share);

       // Fetch and store ShareActionProvider
       mShareActionProvider = (ShareActionProvider) item.getActionProvider();

       // Return true to display menu
       return true;
   }

   // Call to update the share intent
   private void setShareIntent(Intent shareIntent) {
       if (mShareActionProvider != null) {
           mShareActionProvider.setShareIntent(shareIntent);
       }
   }



* 출처 : http://developer.android.com/training/sharing/index.html