반응형
Notice
Recent Posts
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- TIZEN
- hung-up
- AWS
- gradle
- 워치
- OZViewer
- socket.io
- ozd
- git
- Flavors
- NoSuchMethodError
- cloud-firestore
- mosquitto
- firebase-storage
- Java8
- mqtt
- socket-client
- Android
- BottomSheetDialog
- ActivityResult-API
- Galaxy Watch
- JNI
- Firebase
- 오즈뷰어
- firebase-database
- Kotlin
- google-login
- git-push
- Dva
- socket-server
Archives
- Today
- Total
Hyeyeon blog
[Android] Kotlin - SMS Retriever API 본문
반응형
# Google의 SMS 및 Call 권한 정책 변경으로 앱의 주요 기능이 아닌 경우 관련 퍼미션을 요청할 수 없게 되었으며,
대신 퍼미션 요청 없이 SMS Retriever API를 이용하여 문자 메세지의 내용을 얻을 수 있다.
0. 구글 플레이 서비스 버전 확인
- 전제 조건: 구글 플레이 서비스 1.02 버전 이상
- 8자리의 숫자가 반환되는데, 15000000의 경우 15.0을 의미
val gpsVersion = packageManager.getPackageInfo(GoogleApiAvailability.GOOGLE_PLAY_SERVICES_PACKAGE, 0).versionCode
1. dependency 추가
implementation 'com.google.android.gms:play-services-auth:16.0.1' implementation 'com.google.android.gms:play-services-auth-api-phone:16.0.0'
2. SMS Retriever 실행
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
startSMSRetriever()
}
private fun startSMSRetriever(){
val client = SmsRetriever.getClient(this)
val task = client.startSmsRetriever()
task.addOnSuccessListener {
// Start retriever successfully
}
task.addOnFailureListener {
// Failed to start retriever
}
}
3. 문자 메세지 내용 가져오기
3-1. BroadcastReceiver 생성
class SMSBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
if (SmsRetriever.SMS_RETRIEVED_ACTION == intent?.action) {
val extras = intent.extras
val status = extras?.get(SmsRetriever.EXTRA_STATUS) as Status
when (status.statusCode) {
CommonStatusCodes.SUCCESS -> {
// Get SMS message
val message = extras.get(SmsRetriever.EXTRA_SMS_MESSAGE) as String
val format = message.split(":")[1]
val number = format.split("\n")[0] // 인증번호
}
CommonStatusCodes.TIMEOUT -> {
// 5 mitues
return
}
}
}
}
}
3-2. BroadcastReceiver 등록
// AndroidManifest.xml
<application>
...
<receiver android:name=".SMSBroadcastReceiver" android:exported="true">
<intent-filter>
<action android:name="com.google.android.gms.auth.api.phone.SMS_RETRIEVED"></action>
</intent-filter>
</receiver>
</application>
3-3. 동적으로 등록할 경우
(1) 사용할 Activity에 리시버 등록
val intentFilter = IntentFilter()
intentFilter.addAction("com.google.android.gms.auth.api.phone.SMS_RETRIEVED")
this.registerReceiver(broadCastReceiver, intentFilter)
(2) 리시버 해지
private lateinit var smsBroadcaseReceiver: BroadcastReceiver
...
override fun onDestroy() {
if (::smsBroadcaseReceiver.isInitialized) {
this.unregisterReceiver(smsBroadcaseReceiver)
}
super.onDestroy()
}
4. 테스트
1-1. 해시 문자열 생성
fun getAppSignatures(): ArrayList<String>
{ val appCodes :ArrayList<String> = ArrayList() try { // Get all package signatures for the current package val packageName = packageName val packageManager = packageManager val signatures = packageManager.getPackageInfo( packageName, PackageManager.GET_SIGNATURES ).signatures // 앱의 공개키 인증서 // For each signature create a compatible hash for (signature in signatures) { val hash = hash(packageName, signature.toCharsString()) if (hash != null) { appCodes.add(String.format("%s", hash)) } } } catch (e: PackageManager.NameNotFoundException) { Log.e("Hash", "Unable to find package to obtain hash.", e) } return appCodes } private fun hash(packageName: String, signature: String): String? { val HASH_TYPE = "SHA-256" val NUM_HASHED_BYTES = 9 val NUM_BASE64_CHAR = 11 val appInfo = "$packageName $signature" try { val messageDigest = MessageDigest.getInstance(HASH_TYPE) messageDigest.update(appInfo.toByteArray(StandardCharsets.UTF_8)) var hashSignature = messageDigest.digest() // truncated into NUM_HASHED_BYTES hashSignature = Arrays.copyOfRange(hashSignature, 0, NUM_HASHED_BYTES) // encode into Base64 var base64Hash = android.util.Base64. encodeToString(hashSignature, android.util.Base64.NO_PADDING 또는 android.util.Base64.NO_WRAP) base64Hash = base64Hash.substring(0, NUM_BASE64_CHAR) Log.d("HASH", String.format("pkg: %s -- hash: %s", packageName, base64Hash)) return base64Hash } catch (e: NoSuchAlgorithmException) { Log.e("Hash", "hash:NoSuchAlgorithm", e) } return null }
1-2. 서버 또는 ADV에서 수신한 문자 메세지 형식
<#> ExampleApp 코드 : 123ABC78 FA + 9qCX9VSu // getAppSignatures()[0]로 가져온 해시 문자열
[참고 및 출처]
728x90
'개발 > Android' 카테고리의 다른 글
[Android] Recyclerview.Adapter notifyItemChanged 애니메이션 제거 (0) | 2019.03.12 |
---|---|
[Android] 둥근 모서리 레이아웃 적용하기 (0) | 2019.02.15 |
[Android] Kotlin - Higher-order Function (0) | 2019.01.30 |
[Android] Databinding - EditText의 OnTextChanged() 구현 (0) | 2019.01.30 |
[Android] Koin - Dependency Injection Library (0) | 2019.01.27 |
Comments