中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android怎么實現獲取短信驗證碼并自動填充

發布時間:2023-04-18 17:26:55 來源:億速云 閱讀:130 作者:iii 欄目:開發技術

本篇內容主要講解“Android怎么實現獲取短信驗證碼并自動填充”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Android怎么實現獲取短信驗證碼并自動填充”吧!

權限

申請權限

短信屬于隱私權限,Android 6.0后需要動態申請權限。首先在manifest里面注冊權限:

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

在需要用的地方,動態申請下:

String[] smsPermission = {Manifest.permission.READ_SMS, Manifest.permission.RECEIVE_SMS};

小米短信權限問題

本來這樣權限問題就搞定了,但是在小米手機上就不行。小米手機會把短信歸類到通知類權限里:

Android怎么實現獲取短信驗證碼并自動填充

在 ContextCompat.checkSelfPermission 的時候會直接返回true,并且不會彈出權限對話框,而是在實際使用的時候才會咨詢用戶,按理說好像和我們邏輯沒有沖突,但是在使用receiver進行監聽前,不是得確保有權限么?實際效果也是,在沒有權限時,不能獲取到短信的廣播。

小米短信權限解決

在網上找了找辦法,好像也沒多少博文,但是大致有了思路:不是用的時候才申請么?那我就先用一下,再去用receiver監聽。下面是方法:

// 讀取一下試試,能讀取到就有權限
boolean flag = false;
try {
    Uri uri = Uri.parse("content://sms/inbox");
    ContentResolver cr = context.getContentResolver();
    String[] projection = new String[]{"_id"};
    Cursor cur = cr.query(uri, projection, null, null, "date desc");
    if (null != cur) {
        cur.close();
    }
    lag = true;
}catch (Exception e) {
    e.printStackTrace();
}

這里僅針對小米手機啊,對小米手機的判斷我只是用 android.os.Build.MANUFACTURER 簡單判斷了下,如果有更高要求請查找資料。

使用Receiver進行監聽

編寫SmsReceiver

這里也是網上隨便找了個代碼,能用,但是在榮耀手機上卻是偶爾能收到一次,后面幾次就收不到了,打了log也沒進入到onReceive中,這就很離奇了,排查了很久。同樣的代碼,在小米手機上是沒問題的,那就只可能是適配問題了。

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.util.Log;

public class SmsReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        //Toast.makeText(context, "收到信息", Toast.LENGTH_LONG).show();
        Log.d("SmsReceiver", "onReceive: " + intent.getAction());
        if(intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")){
            //intent.getExtras()方法就是從過濾后的意圖中獲取攜帶的數據,
            // 這里攜帶的是以“pdus”為key、短信內容為value的鍵值對
            // android設備接收到的SMS是pdu形式的
            Bundle bundle = intent.getExtras();
            SmsMessage msg;
            if (null != bundle){
                //生成一個數組,將短信內容賦值進去
                Object[] smsObg = (Object[]) bundle.get("pdus");
                //遍歷pdus數組,將每一次訪問得到的數據方法object中
                for (Object object:smsObg){
                    //獲取短信
                    msg = SmsMessage.createFromPdu((byte[])object);
                    //獲取短信內容
                    String content = msg.getDisplayMessageBody();
                    Log.d("SmsReceiver", "onReceive: content = " + content);
                    //獲取短信發送方地址
                    String from = msg.getOriginatingAddress();
                    Log.d("SmsReceiver", "onReceive: from = " + from);

                    // TODO ...
                }
            }
        }
    }
}

使用方法:

// 使用廣播進行監聽
IntentFilter smsFilter = new IntentFilter();
smsFilter.addAction("android.provider.Telephony.SMS_RECEIVED");
smsFilter.addAction("android.provider.Telephony.SMS_DELIVER");
if (smsReceiver == null) {
    smsReceiver = new SmsReceiver();
}
smsReceiver.setCallbackContext(callbackContext);
context.registerReceiver(smsReceiver, smsFilter);

接觸監聽,最好在收到短信的時候就取消注冊廣播:

context.unregisterReceiver(smsReceiver);

解決OPPO手機無法接收短信廣播問題

本來小米榮耀都搞定了,給測試一測,結果又不行了。收不到廣播,用下面的ContentObserver還總拿不到對的數據。找了下資料,發現OPPO手機需要在短信APP進行設置。

ps. 后面發現華為、榮耀都是這樣,會對驗證碼進行保護。可以使用ContentObserver 監聽,能觸發onChange,但是拿不到Uri,不過可以使用查詢,拿到倒敘的第一條數據,取出其中的date屬性,比對監聽時的時間,如果短信兩分鐘有效,那就看看第一條數據是不是在兩分鐘內,如果不是,那就是沒拿到,問題就出在用戶開啟了短信驗證碼保護,可以提示用戶自行輸入驗證碼(畢竟這個不是我們的鍋)。

解決方法: 在短信 -> 短信設置里面 -> 打開禁止后臺應用讀取驗證碼

解決榮耀無法連續監聽短信的問題

既然上面的方法沒用了,只能找新的辦法嘍,網上很多提供了兩種辦法,第二種就是通過ContentResolver去監聽短信添加的更新動作,其實也和廣播類似,代碼如下:

import android.content.Context;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
import android.provider.Telephony;
import android.util.Log;

import androidx.annotation.RequiresApi;

@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public class ReadSmsObserver extends ContentObserver {

    private final Context context;

    public ReadSmsObserver(Handler handler, Context context) {
        super(handler);
        this.context = context;
    }

    private static final String SMS_INBOX_URI = "content://sms/inbox";//API level>=23,可直接使用Telephony.Sms.Inbox.CONTENT_URI,用于獲取cusor
    // private static final String SMS_URI = "content://sms";//API level>=23,可直接使用Telephony.Sms.CONTENT_URI,用于注冊內容觀察者
    private static final String[] PROJECTION = new String[]{
            Telephony.Sms._ID,
            Telephony.Sms.ADDRESS,
            Telephony.Sms.BODY,
            Telephony.Sms.DATE
    };

    @Override
    public void onChange(boolean selfChange, Uri uri) {
        super.onChange(selfChange);
        Log.d("ReadSmsObserver", "onChange: ");
        // 當收到短信時調用一次,當短信顯示到屏幕上時又調用一次,所以需要return掉一次調用
        if(uri.toString().equals("content://sms/raw")){
            return;
        }
        // 讀取短信收件箱,只讀取未讀短信,即read=0,并按照默認排序
        Cursor cursor = context.getContentResolver().query(Uri.parse(SMS_INBOX_URI), PROJECTION,
                Telephony.Sms.READ + "=?", new String[]{"0"}, Telephony.Sms.Inbox.DEFAULT_SORT_ORDER);
        if (cursor == null) return;
        // 獲取倒序的第一條短信
        if (cursor.moveToFirst()) {
            // 讀取短信發送人
            String address = cursor.getString(cursor.getColumnIndex(Telephony.Sms.ADDRESS));
            Log.d("ReadSmsObserver", "onChange: address = " + address);
            // 讀取短息內容
            String smsBody = cursor.getString(cursor.getColumnIndex(Telephony.Sms.BODY));
            Log.d("ReadSmsObserver", "onChange: smsBody = " + smsBody);
            
            // TODO 傳遞出去,最好切下線程

        }
        // 關閉cursor的方法
        cursor.close();
    }
}

用的時候要注冊和取消注冊:

// 使用ContentResolver進行監聽
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    if (smsObserver == null) {
        smsObserver = new ReadSmsObserver(new SmsHandler(), context);
    }
    smsObserver.setCallbackContext(callbackContext);
    context.getContentResolver().registerContentObserver(
        Uri.parse("content://sms/"), true, smsObserver);
}

取消注冊:

context.getContentResolver().unregisterContentObserver(smsObserver);

解決OPPO手機無法拿到最新短信問題

很神奇啊,每次使用ContentObserver去監聽短信變化,明明onChange觸發了,但是去拿短信就是拿不到最新的,開了上面的設置也不行,弄了好久。

最后想的解決辦法是,兩種方式同時監聽,在onChange觸發后等待三秒鐘(開始試了1s還不行),看看有沒有onReceive,如果有就直接使用onReceive的短信,如果沒有再驗證onChange內拿到的短信,看看是不是有效時間內的,連倒敘第一個都在有效時間外,那就是沒拿到了,直接舍棄了。

到此,相信大家對“Android怎么實現獲取短信驗證碼并自動填充”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

扎鲁特旗| 黄浦区| 普宁市| 平陆县| 于田县| 筠连县| 额济纳旗| 蓝山县| 突泉县| 信宜市| 大化| 仁怀市| 嘉祥县| 涞水县| 林周县| 永泰县| 正定县| 蒲江县| 将乐县| 平顶山市| 武威市| 呼伦贝尔市| 太仓市| 周至县| 沛县| 灌云县| 烟台市| 舞钢市| 神农架林区| 嘉禾县| 娄底市| 同江市| 庆安县| 水富县| 陆川县| 南安市| 葵青区| 理塘县| 德保县| 墨江| 兴业县|