サーバーがOTPを送信し、ユーザーがこのOTPをアプリに入力してアプリにサインアップする必要があるAndroidアプリに取り組んでいます。私が欲しいのは、私のアプリがサーバーから送信された OTP を自動的に読み取れるようにすることです。どうすればこれを達成できますか?この点に関するヘルプやガイダンスをいただければ幸いです。
9 に答える
次のような単純なライブラリを使用してみることができます
Gradle 経由でインストールし、アクセス許可を追加した後、onCreate アクティビティのようなメソッドで SmsVerifyCatcher を開始します。
smsVerifyCatcher = new SmsVerifyCatcher(this, new OnSmsCatchListener<String>() {
@Override
public void onSmsCatch(String message) {
String code = parseCode(message);//Parse verification code
etCode.setText(code);//set code in edit text
//then you can send verification code to server
}
});
また、アクティビティのライフサイクル メソッドをオーバーライドします。
@Override
protected void onStart() {
super.onStart();
smsVerifyCatcher.onStart();
}
@Override
protected void onStop() {
super.onStop();
smsVerifyCatcher.onStop();
}
/**
* need for Android 6 real time permissions
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
smsVerifyCatcher.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
public String parseCode(String message) {
Pattern p = Pattern.compile("\\b\\d{4}\\b");
Matcher m = p.matcher(message);
String code = "";
while (m.find()) {
code = m.group(0);
}
return code;
}
Google は READ_SMS 権限の使用を制限しているため、ここでは READ_SMS 権限のないソリューションを使用します。
SMS レトリーバー API
基本的な機能は、Android のクリティカル パーミッション READ_SMS の使用を避け、このメソッドを使用してタスクを実行することです。ブローは必要な手順です。
OTP送信をユーザーの番号に投稿し、SMSレトリーバーAPIがメッセージを取得できるかどうかを確認します
SmsRetrieverClient client = SmsRetriever.getClient(SignupSetResetPasswordActivity.this);
Task<Void> task = client.startSmsRetriever();
task.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
// Android will provide message once receive. Start your broadcast receiver.
IntentFilter filter = new IntentFilter();
filter.addAction(SmsRetriever.SMS_RETRIEVED_ACTION);
registerReceiver(new SmsReceiver(), filter);
}
});
task.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
// Failed to start retriever, inspect Exception for more details
}
});
放送受信機コード
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import com.google.android.gms.auth.api.phone.SmsRetriever;
import com.google.android.gms.common.api.CommonStatusCodes;
import com.google.android.gms.common.api.Status;
public class SmsReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (SmsRetriever.SMS_RETRIEVED_ACTION.equals(intent.getAction())) {
Bundle extras = intent.getExtras();
Status status = (Status) extras.get(SmsRetriever.EXTRA_STATUS);
switch (status.getStatusCode()) {
case CommonStatusCodes.SUCCESS:
// Get SMS message contents
String otp;
String msgs = (String) extras.get(SmsRetriever.EXTRA_SMS_MESSAGE);
// Extract one-time code from the message and complete verification
break;
case CommonStatusCodes.TIMEOUT:
// Waiting for SMS timed out (5 minutes)
// Handle the error ...
break;
}
}
}
}
最終段階。この受信機をマニフェストに登録します
<receiver android:name=".service.SmsReceiver" android:exported="true">
<intent-filter>
<action android:name="com.google.android.gms.auth.api.phone.SMS_RETRIEVED"/>
</intent-filter>
</receiver>
SMS は次のようになっている必要があります。
<#> Your OTP code is: 6789
QWsa8754qw2
ここで QWsa8754qw2 は、独自のアプリケーションの 11 文字のハッシュ コードです。このリンクに従ってください
- 140バイト以内
- 接頭辞 <#> で始める
- アプリを識別する 11 文字のハッシュ文字列で終わります
をインポートcom.google.android.gms.auth.api.phone.SmsRetriever
するには、アプリの build.gradle に次の行を追加することを忘れないでください。
implementation "com.google.android.gms:play-services-auth-api-phone:16.0.0"
そのようなものを実装しました。しかし、メッセージが届いたときに私が行ったことは次のとおりです。6 桁のコードのみを取得し、それをインテントにバンドルして、それを必要とするアクティビティまたはフラグメントに送信し、コードを検証します。この例は、すでに SMS を取得する方法を示しています。LocalBrodcastManagerを使用して送信する方法については、以下のコードを参照してください。メッセージにグリーティングなどのテキストが含まれている場合は、より適切に標準化してください。たとえば、「Your validation code is: 84HG73」のように、2 つの int、2 つの [capital] 文字、2 つの int を意味する正規表現パターンを作成できます。([0-9]){2}([A-Z]){2}([0-9]){2}
幸運を!
メッセージから不要な情報をすべて破棄した後
Intent intent = new Intent("AddedItem");
intent.putExtra("items", code);
LocalBroadcastManager.getInstance(getActivity()).sendBroadcast(intent);
そして、それを受け取るフラグメント/アクティビティ
@Override
public void onResume() {
LocalBroadcastManager.getInstance(getActivity()).registerReceiver(receiver, new IntentFilter("AddedItem"));
super.onResume();
}
@Override
public void onPause() {
super.onDestroy();
LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(receiver);
}
そして、収集したペイロードを処理するためのコード
private BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction()) {
final String message = intent.getStringExtra("message");
//Do whatever you want with the code here
}
}
};
少しは役に立ちますか。コールバックを使用して改善しました
遅いことはわかっていますが、他の人にとってこれを簡単にするために、以前に書いた解決策を次に示します。このライブラリリンクを使用します。何もいじる必要はありません。依存関係を追加した後、このメソッドを使用するだけです。
OtpFetcher.getInstance().verifyOtpByMatchingString(this, "OTP", 21000, object : OtpListener {
override fun onReceived(messageItem: MessageItem) {
Toast.makeText(this@MainActivity, "" + messageItem, Toast.LENGTH_SHORT).show()
}
override fun onTimeOut() {
Toast.makeText(this@MainActivity, "TimeOut", Toast.LENGTH_SHORT).show()
}
})
例として、メッセージのコンテキスト、検索文字列を渡す必要があります
メッセージで OTP を期待していますが、「OTP」を渡し、OTP をリッスンする時間のタイムアウトを指定すると、それだけです。OnRecieved CallBack でメッセージを単純な形式で取得します。