Tech & Programming/모바일(Android, Flutter)

Intent를 이용한 카카오톡 / SMS 텍스트, 이미지 보내기

소스코드 요리사 2018. 3. 26. 23:43

지난 번 새해 때 급하게 만들었던 인사말 관련 안드로이드 어플리케이션 때 사용한 기능을 소개해 드릴려고 합니다.

버튼을 클릭하면 텍스트나 이미지를 카카오 톡 또는 문자메시지로 보내는 코드입니다.


1. 텍스트 보내기

텍스트 보내기는 간단합니다. 기본 코드는 아래와 같습니다. 아래 코드로 응용해서 다양하게 이용할 수 있을 것으로 생각됩니다.


1) 문자메시지

    
     String message = "보낼 내용";
     Intent intent = new Intent(Intent.ACTION_VIEW);
     intent.putExtra("sms_body", message );
     intent.setType("vnd.android-dir/mms-sms");
      startActivity(intent);


2) 카카오 톡

  
     String message = "보낼 내용";
     Intent intent = new Intent(Intent.ACTION_SEND);
     intent.setType("text/plain");
     intent.putExtra(Intent.EXTRA_TEXT, message );
     intent.setPackage("com.kakao.talk");
     startActivity(intent);



2. 이미지 보내기

  외부저장소 안의 이미지를 보내기 위해서는 먼저 공통적으로 AndroidManifest에 외부저장소 읽기 또는 쓰기 permission 추가가 필요합니다.

저는 읽고 쓰기가 다 필요해서 아래 권한을 넣었습니다. 읽기만 필요하신 분은 READ_EXTERNAL_STORAGE 권한만 넣으셔도 됩니다.

참고로 WRITE_EXTERNAL_STORAGE 권한을 넣으시면 읽기/쓰기 모두 권한이 부여됩니다.

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />


1) 문자메시지 

문자메시지에 이미지를 첨부하는 기본 코드는 아래와 같습니다. 코드를 보시면 intent 에 이미지 파일의 uri를 넘기시는 것을 볼 수 있습니다.

   private void sendMMS(Uri uri) {
        try {
            Intent intent = new Intent(Intent.ACTION_SEND);
            intent.setType("image/*");
            intent.putExtra(Intent.EXTRA_STREAM, uri);
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            startActivityForResult(Intent.createChooser(intent, "send"), REQUEST_IMG_SEND);
        }
        catch (ActivityNotFoundException e) {
        Toast.makeText(getApplicationContext(), R.string.alert_no_sms_activity, Toast.LENGTH_SHORT).show();
        }
    }  

여기서 문제가 파일 uri 로 넘기면 계속 앱이 clash가 났습니다. 원인을 파악해보니 누가(nougat) 버전부터 패키지 도메인 외부에서 file uri를 전달하면 안되고, FileProvider를 사용해야한다는 것이 었습니다.


패키지 도메인 외부에서 file:// URI를 전달하면 수신기가 액세스 불가능한 경로로 남아 있을 수 있습니다. 따라서 file:// URI를 전달하려고 시도하면 FileUriExposedException이 트리거됩니다. 개인 파일의 내용을 공유하기 위해 권장되는 방법은 FileProvider를 사용하는 것입니다

[출처 : https://developer.android.com/about/versions/nougat/android-7.0-changes.html?hl=ko]


상세한 FileProvider 가 무엇인지 알고 싶으시거나 자세한 사용법은 아래 주소의 구글 개발자 레퍼런스를 보시면 됩니다.

  [https://developer.android.com/reference/android/support/v4/content/FileProvider.html?hl=ko]



저는 간략한 사용법 위주로 설명하겠습니다.


(1) Androidmanifest.xml 파일의 <application> 태그 안에 아래 FileProvider 코드를 넣습니다.

<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="어플리케이션 패키지명"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>


(2) /res 내에 xml 이라는 폴더를 만들고 file_paths.xml 파일을 만들고 아래 코드를 작성합니다. 

    제 어플리케이션은 Pictures/greeting 폴더에 이미지가 저장되고, 이 폴더의 이미지를 read해서 uri로 전달합니다.

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="hidden" path="/Pictures/greeting" />
</paths>


(3) 실제 위 sendMMS 함수에 파라메터로 URI를 전달하기 위한 코드는 아래와 같습니다. 

    누가(nougat) 전 버전은 File URI를 그대로 사용하고 이 후 버전부터 FileProvider를 사용하도록 했습니다.

Uri providerURI; // sendMMS 함수 파라메터로 전달할 URI 변수 if(Build.VERSION.SDK_INT < 24) { providerURI = Uri.fromFile(savefile); // savefile은 MMS로 보낼 이미지 파일의 File 형식의 변수입니다. } else { providerURI = FileProvider.getUriForFile(getBaseContext(), getPackageName(), savefile); }


(4) 위 sendMMS() 함수로 MMS를 보냅니다.



2) 카카오톡

카카오톡도 위 MMS 와 동일하게 URI를 파라메터를 넘겨 아래와 같은 코드를 사용하여 카카오톡으로 이미지를 보냈습니다.

private void sendKaKao(Uri uri) { try { Intent intent = new Intent(Intent.ACTION_SEND); intent.setType("image/*"); intent.putExtra(Intent.EXTRA_STREAM, uri); intent.setPackage("com.kakao.talk"); startActivityForResult(intent,REQUEST_IMG_SEND); } catch (ActivityNotFoundException e) { Uri uriMarket = Uri.parse("market://deatils?id=com.kakao.talk"); Intent intent = new Intent(Intent.ACTION_VIEW, uriMarket); startActivity(intent); } }