지난 번 새해 때 급하게 만들었던 인사말 관련 안드로이드 어플리케이션 때 사용한 기능을 소개해 드릴려고 합니다.
버튼을 클릭하면 텍스트나 이미지를 카카오 톡 또는 문자메시지로 보내는 코드입니다.
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); } }
'Tech & Programming > 모바일(Android, Flutter)' 카테고리의 다른 글
ViewHolder 가 무엇인가요? (4) | 2019.04.30 |
---|---|
안드로이드 http 프로토콜 접속 시 예외발생 조치 (ERR CLEARTEXT NOT PERMITTED) (18) | 2019.01.23 |
2018 GDG DevFest in 서울 참석 후기 (0) | 2018.11.11 |
AlertDialog의 setSingleChoiceItems 리스트 아이템이 안보이는 경우 확인사항 (0) | 2018.09.05 |
Soundpool 재생이 안되는 경우 해결방법 (Soundpool.load 딜레이) (0) | 2018.08.18 |