網(wǎng)頁(yè)界面設(shè)計(jì)系統(tǒng)seo描述是什么
本文主要介紹國(guó)外google上線的app 短信自動(dòng)填充方案。
本方案主要是使用google提出的,防止開發(fā)者使用SMS相關(guān)權(quán)限造成的用戶信息泄露
目錄
注意點(diǎn):
1、本方式不適合華為手機(jī),華為有自己的獲取方式
2、本方式不需要添加任何短信權(quán)限
3、項(xiàng)目版本
開發(fā)成本:
Android代碼
1、導(dǎo)庫(kù)
1)在項(xiàng)目根目錄的build.gradle中添加下面代碼
2)項(xiàng)目級(jí)build.gradle引用庫(kù)
2、注冊(cè)廣播
1)靜態(tài)注冊(cè)
2)動(dòng)態(tài)注冊(cè)
3、啟動(dòng)監(jiān)聽(tīng)
4、廣播代碼
其他開發(fā)成本
短信模板 (短信后i按加上11位哈市值)
1)命令(mac 命令)
2)代碼,放入項(xiàng)目中運(yùn)行,打包、啟動(dòng)app(注意debug簽名與正是簽名包的不同,正式的hashcode? 需要正式打包,然后打印出來(lái)))
注意點(diǎn):
1、本方式不適合華為手機(jī),華為有自己的獲取方式
2、本方式不需要添加任何短信權(quán)限
3、項(xiàng)目版本
compileSdkVersion>=34
minSdkVersion>=19
開發(fā)成本:
app需要集成兩個(gè)google庫(kù),后端只需要改短信模板,在短信后面添加11位hash值,hash值生成方式在下面鏈接可以看到
google開發(fā)地址(國(guó)內(nèi)需要翻墻)
Android代碼
1、導(dǎo)庫(kù)
1)在項(xiàng)目根目錄的build.gradle中添加下面代碼
buildscript {repositories {...google()mavenCentral()}
}allprojects {repositories { google()mavenCentral()}
}
2)項(xiàng)目級(jí)build.gradle引用庫(kù)
dependencies {implementation 'com.google.android.gms:play-services-auth:21.2.0'implementation 'com.google.android.gms:play-services-auth-api-phone:18.1.0'
}
2、注冊(cè)廣播
1)靜態(tài)注冊(cè)
<receiverandroid:name="<路徑>.MySMSBroadcastReceiver"android:exported="true"android:permission="com.google.android.gms.auth.api.phone.permission.SEND"><intent-filter><action android:name="com.google.android.gms.auth.api.phone.SMS_RETRIEVED" /></intent-filter></receiver>
2)動(dòng)態(tài)注冊(cè)
if(smsBrod==null){smsBrod= MySMSBroadcastReceiver(this,null)}val intentFilter = IntentFilter();intentFilter.addAction(SmsRetriever.SMS_RETRIEVED_ACTION);if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {this@TestAlendActivity.registerReceiver(smsBrod,intentFilter,SmsRetriever.SEND_PERMISSION,null, Context.RECEIVER_EXPORTED)}
3、啟動(dòng)監(jiān)聽(tīng)
fun googleMSM() {val client = SmsRetriever.getClient(this)val task: Task<Void> = client.startSmsRetriever()task.addOnSuccessListener(OnSuccessListener<Void?> {Log.i("SMS_CON", "googleMSM addOnSuccessListener")if(smsBrod==null){smsBrod= MySMSBroadcastReceiver(this,null)}val intentFilter = IntentFilter();intentFilter.addAction(SmsRetriever.SMS_RETRIEVED_ACTION);if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {this@TestAlendActivity.registerReceiver(smsBrod,intentFilter,SmsRetriever.SEND_PERMISSION,null, Context.RECEIVER_EXPORTED)}})task.addOnFailureListener(OnFailureListener {Log.i("SMS_CON", "googleMSM addOnFailureListener")})}
4、廣播代碼
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;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;import org.json.JSONException;
import org.json.JSONObject;import java.lang.ref.SoftReference;
import java.util.regex.Matcher;
import java.util.regex.Pattern;/*** BroadcastReceiver to wait for SMS messages. This can be registered either* in the AndroidManifest or at runtime. Should filter Intents on* SmsRetriever.SMS_RETRIEVED_ACTION.*/
public class MySMSBroadcastReceiver extends BroadcastReceiver {public MySMSBroadcastReceiver() {}@Overridepublic void onReceive(Context context, Intent intent) {Log.i("SMS_CON", "googleMSM MySMSBroadcastReceiver action=" + intent.getAction());if (SmsRetriever.SMS_RETRIEVED_ACTION.equals(intent.getAction())) {Bundle extras = intent.getExtras();Status status = (Status) extras.get(SmsRetriever.EXTRA_STATUS);Log.i("SMS_CON", "status =" + status);if(status!=null){switch (status.getStatusCode()) {case CommonStatusCodes.SUCCESS:// (Optional) Get SMS Sender address - only available in// GMS version 24.20 onwards, else it will return null
// String senderAddress = extras.getString(SmsRetriever.EXTRA_SMS_ORIGINATING_ADDRESS);// Get SMS message contentsString message = extras.getString(SmsRetriever.EXTRA_SMS_MESSAGE);// Extract one-time code from the message and complete verification// by sending the code back to your server.Log.i("SMS_CON", "message =" + message);if (message != null) {Pattern code = Pattern.compile("(\\d{6})");Matcher matcher = code.matcher(message);String otp = "";if (matcher.find()) {otp = matcher.group(0);} else {otp = message;}Log.i("SMS_CON", "otp =" + otp);Toast.makeText(context,"otp=\n"+otp,Toast.LENGTH_LONG).show();}break;case CommonStatusCodes.TIMEOUT:// Waiting for SMS timed out (5 minutes)// Handle the error ...Log.i("SMS_CON", "TIMEOUT =");break;}}}}
}
其他開發(fā)成本
短信模板 (短信后i按加上11位哈市值)
Hash值生成方式
1)命令(mac 命令)
keytool?-exportcert?-keystore keystory名稱.jks?-storepass 你的密碼 -alias 別名 |?xxd?-p??|?tr?-d?"[:space:]"?|?echo?-n 你的包名 `cat`?|?shasum?-a?256?|?tr?-d?"[:space:]-"?|?xxd?-r?-p?|?base64?|?cut?-c1-11
2)代碼,放入項(xiàng)目中運(yùn)行,打包、啟動(dòng)app(注意debug簽名與正是簽名包的不同,正式的hashcode? 需要正式打包,然后打印出來(lái)))
aab文件也可以通過(guò)命令安裝到手機(jī),網(wǎng)上搜一下?bundletool.jar 這個(gè)工具
import android.annotation.TargetApi;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
import android.util.Base64;
import android.util.Log;import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;public class AppSignatureHashHelper extends ContextWrapper {public static final String TAG = AppSignatureHashHelper.class.getSimpleName();private static final String HASH_TYPE = "SHA-256";public static final int NUM_HASHED_BYTES = 9;public static final int NUM_BASE64_CHAR = 11;public AppSignatureHashHelper(Context context) {super(context);}public ArrayList<String> getAppSignatures() {ArrayList<String> appSignaturesHashs = new ArrayList<>();try {String packageName = getPackageName();PackageManager packageManager = getPackageManager();Signature[] signatures = packageManager.getPackageInfo(packageName,PackageManager.GET_SIGNATURES).signatures;for (Signature signature : signatures) {String hash = hash(packageName, signature.toCharsString());if (hash != null) {appSignaturesHashs.add(String.format("%s", hash));}}} catch (Exception e) {Log.e(TAG, "Package not found", e);}return appSignaturesHashs;}@TargetApi(19)private static String hash(String packageName, String signature) {String appInfo = packageName + " " + signature;try {MessageDigest messageDigest = MessageDigest.getInstance(HASH_TYPE);messageDigest.update(appInfo.getBytes(StandardCharsets.UTF_8));byte[] hashSignature = messageDigest.digest();hashSignature = Arrays.copyOfRange(hashSignature, 0, NUM_HASHED_BYTES);String base64Hash = Base64.encodeToString(hashSignature, Base64.NO_PADDING | Base64.NO_WRAP);base64Hash = base64Hash.substring(0, NUM_BASE64_CHAR);return base64Hash;} catch (NoSuchAlgorithmException e) {Log.e(TAG, "No Such Algorithm Exception", e);}return null;}
}
調(diào)用方式
?String hashcodeStr= AppSignatureHashHelper(this).getAppSignatures()
上面會(huì)生成11位hash值,放在短信后面就行了
***以上是獲取短信,短信自動(dòng)填充代碼就不寫了,拿到字符串 設(shè)置到輸入框就行,推薦按使用動(dòng)態(tài)注冊(cè),可以給廣播傳入回調(diào)接口,處理返回的驗(yàn)證碼(otp)
到這里就完成了,上面獲取命令的方式是通過(guò)自己簽名的方式,如果是讓google生成簽名,則需要去看鏈接里的步驟,比較詳細(xì)
測(cè)試的話 可以讓別人發(fā)短信給你 ,在app里會(huì)受到廣播