主頁 > 移動端開發 > 如何實作Android指紋登錄

如何實作Android指紋登錄

2021-09-30 08:40:41 移動端開發

一、概述

指紋識別通過指紋傳感器采集資訊,進行指紋影像的預處理,然后進行特征點提取,最后進行特征匹配,一般指紋識別的用途有:系統解鎖、應用鎖、支付認證、普通的登錄認證,

  • 指紋識別兩種場景

本地識別:在本地完成指紋的識別后,跟本地資訊系結登陸;

后臺互動:在本地完成識別后,將資料傳輸到服務器;

  無論是本地還是與服務器互動,都需要對資訊進行加密,通常來說,與本地互動的采用對稱加密,與服務器互動則采用非對稱加密,下面我們來簡單介紹下對稱加密和非對稱加密

  • 對稱加密、非對稱加密和簽名

在正式使用指紋識別功能之前,有必要先了解一下對稱加密和非對稱加密的相關內容

對稱加密:

采用單密鑰密碼系統的方法,同一密鑰作為加密和解密的工具,通過密鑰控制加密和解密的指令,演算法規定如何加密和解密,優點是演算法公開、加密解密速度快、效率高,缺點是發送前的雙方保持統一密鑰,如果泄露則不安全,通常由AES、DES加密演算法等;

非對稱加密:

非對稱加密演算法需要兩個密鑰來進行加密和解密,這兩個秘鑰是公開密鑰(簡稱公鑰)和私有密鑰(簡稱私鑰),如果一方用公鑰進行加密,接受方應用私鑰進行解密,反之發送方用私鑰進行加密,接收方用公鑰進行解密,由于加密和解密使用的不是同一密鑰,故稱為非對稱加密演算法;與對稱加密演算法相比,非對稱加密的安全性得到了很大的提升,但是效率上則低了很多,因為解密加密花費的時間更長了,所以適合資料量少的加密,通常有RSA,ECC加密演算法等等

其中涉及到很多相關的加密演算法可參考:java安全之加密技術_itheimach的專欄-CSDN博客_java安全加密

Java使用Cipher類實作加密,包括DES,DES3,AES和RSA加密 - 蔡昭凱 - 博客園

Android保存私密資訊-強大的keyStore(譯) - 簡書

Android KeyStore + FingerprintManager 存盤密碼_lintcgirl的博客-CSDN博客_android keystore

二:指紋識別的兼容性和安全性問題

首先說兼容性,指紋識別的 API 是 Google 在 Android 6.0 開放出來的,

在 Android 6.0 以下的系統上,某些手機廠商自行支持了指紋識別,如果我們的 APP 要兼容這些設備,就還要集成廠商的指紋識別的SDK,這是最大的兼容性問題,不過,現在 Android 6.0 以下的設備已經很少了,其中支持指紋識別的設備就更少了,不對其進行兼容,我認為也是可以的,

在Android 6.0 以上的系統上,由于廠商對 Android 系統和指紋識別模塊的定制化普遍,導致會出現一些兼容性問題,這個沒有什么好的辦法,就需要開發者見招拆招了,已經踩過坑的開發者很多,大家可以到網上搜索相關的文章看,

然后說下安全性,由于已添加的指紋是存盤在手機上的,Google API 驗證指紋后僅僅回傳 true 或者 false,我們是很難無條件相信這個識別結果的,比如說用戶的手機 root 了或者是自定制設備,指紋識別是有可能被劫持進而回傳有誤的識別結果的,

好在這種情況發生的概率比較低,如果指紋識別的應用場景非交易非支付,僅僅是類似于 “啟動 APP 進行指紋驗證” 這樣的情況的話,Google API 提供的指紋識別就夠用了,

三:兼容安卓6.0、9.0的指紋識別

指紋識別是在Android 6.0以后新增的功能,在使用的時候需要先判斷手機的系統版本是否為安卓6.0以上

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {}
  • AndroidManifest添加權限
 <!--AndroidP(9.0)時 生物識別權限-->
    <uses-permission android:name="android.permission.USE_BIOMETRIC" />
     <!--AndroidP(6.0)時 開啟觸摸傳感器與身份認證的權限-->
    <uses-permission android:name="android.permission.USE_FINGERPRINT" />
  • 檢查設別是否支持指紋識別

  /**
     * 檢查設別是否支持指紋識別
     *
     * @return
     */
    public static SupportResult checkSupport(Context context) {
       //指紋系統服務
        FingerprintManager fingerprintManager = context.getSystemService(FingerprintManager.class);
        //判斷硬體是否支持指紋
        if (!fingerprintManager.isHardwareDetected()) {
            return SupportResult.DEVICE_UNSUPPORTED;
        }
        KeyguardManager keyguardManager = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
        //判斷是否處于安全保護中(你的設備必須是使用螢屏鎖保護的,這個螢屏鎖可以是password,PIN或者圖案都行)  判斷 是否開啟鎖屏密碼
        if (!keyguardManager.isKeyguardSecure()) {
            return SupportResult.SUPPORT_WITHOUT_KEYGUARD;
        }
        //設備支持且有指紋資料
        if (fingerprintManager.hasEnrolledFingerprints()) {
            return SupportResult.SUPPORT;
        }
        //設備支持指紋識別但是沒有指紋資料
        return SupportResult.SUPPORT_WITHOUT_DATA;

    }

1、先判斷硬體是否支持指紋識別

指紋識別肯定要求你的設備上有指紋識別的硬體,因此在運行時需要檢查系統當中是不是有指紋識別的硬體

2、判斷是否處于安全保護中

(你的設備必須是使用螢屏鎖保護的,這個螢屏鎖可以是password,PIN或者圖案都行) 即判斷 是否開啟鎖屏密碼,如果未設定則指導用戶跳轉手機設定頁面進行設定,

3、系統中是不是有注冊的指紋

在android 6.0中,普通app要想使用指紋識別功能的話,用戶必須首先在setting中注冊至少一個指紋才行,否則是不能使用的,如果未設定則指導用戶跳轉手機設定頁面進行設定,

  • 跳轉設定頁面

根據不同的手機,跳轉到指紋錄入界面,如果沒有檢測到手機的品牌,就提醒用戶手動去指紋錄入

Android-引導用戶指紋錄入 - Android原創 - 博客園

根據6.0、9.0分別呼叫不同的API進行指紋識別

一:基于Android 6.0 實作指紋識別

方法authenticate

采用FingerprintManager類,進行指紋識別中最關鍵的方法authenticate,調起指紋識別掃描器進行指紋識別

FingerprintManager.authenticate(CryptoObject crypto, CancellationSignal cancel,
 int flags, AuthenticationCallback callback, Handler handler);

我們來看一下這個介面:


上圖是google的api檔案中的描述,現在我們挨個解釋一下這些引數都是什么:

  • crypto這是一個加密類的物件

指紋掃描器會使用這個物件來判斷認證結果的合法性,這個物件可以是null,但是這樣的話,就意味這app無條件信任認證的結果,雖然從理論上這個程序可能被攻擊,資料可以被篡改,這是app在這種情況下必須承擔的風險,因此,建議這個引數不要置為null,這個類的實體化有點麻煩,主要使用javax的security介面實作,后面我的demo程式中會給出一個helper類,這個類封裝內部實作的邏輯,開發者可以直接使用我的類簡化實體化的程序,

  • cancel 這個是CancellationSignal類的一個物件

這個物件用來在指紋識別器掃描用戶指紋的是時候取消當前的掃描操作,如果不取消的話,那么指紋掃描器會移植掃描直到超時(一般為30s,取決于具體的廠商實作),

不及時取消的話,指紋掃描器就會一直掃描,直至超時,這會造成兩個問題:

(1) 耗電;

(2) 在超時時間內,用戶將無法再次調起指紋識別,

同樣,這個引數在 Android 6.0 是 @Nullable,在 Android 9.0 之后是 @NonNull ,由于上述的原因,不建議傳 null ,

  • flags 標識位

根據上圖的檔案描述,這個位暫時應該為0,這個標志位應該是保留將來使用的,

  • callback 這個是FingerprintManager.AuthenticationCallback類的物件

這個是這個介面中除了第一個引數之外最重要的引數了,當系統完成了指紋認證程序(失敗或者成功都會)后,會回呼這個物件中的介面,通知app認證的結果,這個引數不能為NULL,

  • handler 這是Handler類的物件

如果這個引數不為null的話,那么FingerprintManager將會使用這個handler中的looper來處理來自指紋識別硬體的訊息,通常來講,開發這不用提供這個引數,可以直接置為null,因為FingerprintManager會默認使用app的main looper來處理,

取消指紋掃描

上面我們提到了取消指紋掃描的操作,這個操作是很常見的,這個時候可以使用CancellationSignal這個類的cancel方法實作:

這個方法專門用于發送一個取消的命令給特定的監聽器,讓其取消當前操作,
因此,app可以在需要的時候呼叫cancel方法來取消指紋掃描操作

創建CryptoObject類物件

上面我們分析FingerprintManager的authenticate方法的時候,看到這個方法的第一個引數就是CryptoObject類的物件,現在我們看一下這個物件怎么去實體化,
我們知道,指紋識別的結果可靠性是非常重要的,我們肯定不希望認證的程序被一個第三方以某種形式攻擊,因為我們引入指紋認證的目的就是要提高安全性,但是,從理論角度來說,指紋認證的程序是可能被第三方的中間件惡意攻擊的,常見的攻擊的手段就是攔截和篡改指紋識別器提供的結果,這里我們可以提供CryptoObject物件給authenticate方法來避免這種形式的攻擊,

FingerprintManager.CryptoObject

是基于Java加密API的一個包裝類,并且被FingerprintManager用來保證認證結果的完整性,通常來講,用來加密指紋掃描結果的機制就是一個Javax.Crypto.Cipher物件,Cipher物件本身會使用由應用呼叫Android keystore的API產生一個key來實作上面說道的保護功能,

創建密鑰
創建密鑰要涉及到兩個類:KeyStore(俗稱密鑰商店) 和 KeyGenerator(密鑰發電機)

 三個類:
        KeyGenerator產生密鑰
        KeyStore存放獲取密鑰
        Cipher,是一個按照一定的加密規則,將資料進行加密后的一個物件

KeyStore 是用于存盤、獲取密鑰(Key)的容器,獲取 KeyStore的方法如下:

try {
    mKeyStore = KeyStore.getInstance("AndroidKeyStore");
} catch (KeyStoreException e) {
    throw new RuntimeException("Failed to get an instance of KeyStore", e);
}

產生密鑰

    /**
     * @des 根據當前指紋庫創建一個密鑰
     */
    void createKey() {
      
 // 創建KeyGenerator物件
            mKeyGenerator = KeyGenerator.getInstance(
                    KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
                //生成密鑰引數  1.別名,這個名字可以是任意的  2.設定意圖,是加密還是解密
                KeyGenParameterSpec.Builder builder = new KeyGenParameterSpec.Builder(KEYSTORE_ALIAS,
                        KeyProperties.PURPOSE_ENCRYPT |
                                KeyProperties.PURPOSE_DECRYPT)
                        //保證了只有指定的block模式下可以加密,解密資料,如果使用其它的block模式,將會被拒絕
                        .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
                        // 設定需要用戶驗證
                        .setUserAuthenticationRequired(true)
                        .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7);

                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                    builder.setInvalidatedByBiometricEnrollment(true);
                }
                //始化KeyGenerator
                mKeyGenerator.init(builder.build());
                //生成了SecretKey(加密密鑰成功)
                mKeyGenerator.generateKey();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

創建并初始化 Cipher 物件

Cipher 物件是一個按照一定的加密規則,將資料進行加密后的一個物件,呼叫指紋識別功能需要使用到這個物件,創建 Cipher 物件很簡單,如同下面代碼那樣:

 /**
     * @des 創建cipher (Cipher類提供了加密和解密的功能) AES/CBC/PKCS7Padding
     */
    public Cipher createCipher() {
        try {
            //getInstance(String transformation)  回傳實作指定轉換的 Cipher 物件,
            // 引數按"演算法/模式/填充模式"
            return Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/"
                    + KeyProperties.BLOCK_MODE_CBC + "/"
                    + KeyProperties.ENCRYPTION_PADDING_PKCS7);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

然后使用剛才創建好的密鑰,初始化 Cipher 物件:

  /**
     * @des 初始化Cipher ,根據KeyPermanentlyInvalidatedExceptiony例外判斷指紋庫是否發生了變化
     */
    public boolean initCipher(Cipher cipher) {
        try {
            keyStore.load(null);
            //獲取密鑰
            SecretKey key = (SecretKey) keyStore.getKey(KEYSTORE_ALIAS, null);
            if (cipher == null) {
                cipher = createCipher();
            }
            //ENCRYPT_MODE 加密模式,key為密鑰    進行加密
            cipher.init(Cipher.ENCRYPT_MODE, key);
            return false;
        } catch (KeyPermanentlyInvalidatedException | UnrecoverableKeyException e) {
            //該密鑰已被永久無效 |未能獲得有關私鑰
            //指紋庫是否發生了變化,這里會拋KeyPermanentlyInvalidatedException
            return true;
        } catch (KeyStoreException | CertificateException | IOException
                | NoSuchAlgorithmException | InvalidKeyException e) {
            //密鑰庫例外|
//            throw new RuntimeException("Failed to init Cipher", e);
            e.printStackTrace();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return true;
        }
    }

這里需要強調一點,在以下情況下,android會認為當前key是無效的:
1. 一個新的指紋image已經注冊到系統中
2. 當前設備中的曾經注冊過的指紋現在不存在了,可能是被全部洗掉了
3. 用戶關閉了螢屏鎖功能
4. 用戶改變了螢屏鎖的方式
當上面的情況發生的時候,Cipher.init方法都會拋出KeyPermanentlyInvalidatedException的例外

處理用戶的指紋認證結果

前面我們分析authenticate介面的時候說道,呼叫這個介面的時候必須提供FingerprintManager.AuthenticationCallback類的物件,這個物件會在指紋認證結束之后系統回呼以通知app認證的結果的,在android 6.0中,指紋的掃描和認證都是在另外一個行程中完成(指紋系統服務)的,因此底層什么時候能夠完成認證我們app是不能假設的,因此,我們只能采取異步的操作方式,也就是當系統底層完成的時候主動通知我們,通知的方式就是通過回呼我們自己實作的FingerprintManager.AuthenticationCallback類,這個類中定義了一些回呼方法以供我們進行必要的處理:

下面我們簡要介紹一下這些介面的含義:
1. OnAuthenticationError(int errorCode, ICharSequence errString)

這個介面會再系統指紋認證出現不可恢復的錯誤的時候才會呼叫,并且引數errorCode就給出了錯誤碼,標識了錯誤的原因,測驗了下一般是OnAuthenticationFailed出現5次,會進入OnAuthenticationError回呼中,接下來再次進行識別時會一直回呼這個方法,這個時候app能做的只能是提示用戶重新嘗試一遍,即指紋傳感器會關閉一段時間,在下次呼叫authenticate時,會出現禁用期(時間依廠商不同30s,1分都有)


2. OnAuthenticationFailed()

這個介面會在系統指紋認證失敗的情況的下才會回呼,注意這里的認證失敗和上面的認證錯誤是不一樣的,雖然結果都是不能認證,認證失敗是指所有的資訊都采集完整,并且沒有任何例外,但是這個指紋和之前注冊的指紋是不相符的;但是認證錯誤是指在采集或者認證的程序中出現了錯誤,比如指紋傳感器作業例外等,也就是說認證失敗是一個可以預期的正常情況,而認證錯誤是不可預期的例外情況,


3. OnAuthenticationHelp(int helpMsgId, ICharSequence helpString)

上面的認證失敗是認證程序中的一個例外情況,我們說那種情況是因為出現了不可恢復的錯誤,而我們這里的OnAuthenticationHelp方法是出現了可以恢復=復的例外才會呼叫的,什么是可以恢復的例外呢?一個常見的例子就是:手指移動太快,當我們把手指放到傳感器上的時候,如果我們很快地將手指移走的話,那么指紋傳感器可能只采集了部分的資訊,因此認證會失敗,但是這個錯誤是可以恢復的,因此只要提示用戶再次按下指紋,并且不要太快移走就可以解決,


4. OnAuthenticationSucceeded(FingerprintManagerCompati.AuthenticationResult result)

這個介面會在認證成功之后回呼,我們可以在這個方法中提示用戶認證成功,這里需要說明一下,如果我們上面在呼叫authenticate的時候,我們的CryptoObject不是null的話,那么我們在這個方法中可以通過AuthenticationResult來獲得Cypher物件然后呼叫它的doFinal方法,doFinal方法會檢查結果是不是會攔截或者篡改過,如果是的話會拋出一個例外,當我們發現這些例外的時候都應該將認證當做是失敗來來處理,為了安全建議大家都這么做,

關于上面的介面還有2點需要補充一下:
1. 上面我們說道OnAuthenticationError 和 OnAuthenticationHelp方法中會有錯誤或者幫助碼以提示為什么認證不成功,Android系統定義了幾個錯誤和幫助碼在FingerprintManager類中,如下

我們的callback類實作的時候最好需要處理這些錯誤和幫助碼, 具體大家可以詳細了解下,

2. 當指紋掃描器正在作業的時候,如果我們取消本次操作的話,系統也會回OnAuthenticationError方法的,只是這個時候的錯誤碼是FingerprintManager.FINGERPRINT_ERROR_CANCELED(值為5、指紋操作以取消),如果要區別判斷,則大家可以去獲取對呀的值進行區別判斷,

基于Android 9.0 實作指紋識別

在AndroidP(9.0)時候,官方不再推薦使用FingerprintManager,標記為@Deprecated,開放BiometricPrompt新的API

AndroidManifest添加權限

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

Android 9.0及以上的指紋認證實作,相比Android 6.0 指紋識別框可以自定義,而9.0不允許開發者自定義指紋識別框

 this.mBiometricPrompt = new BiometricPrompt
                .Builder(activity)
                .setTitle("我是指紋彈出窗的標題")
                .setDescription("我是它的詳細資訊")
                .setNegativeButton("按鈕名稱 一般是取消",
                        activity.getMainExecutor(), new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {
                                mSelfCanceled = true;
                                mFingerCallback.onCancel();
                                mCancellationSignal.cancel();
                            }
                        })
                .build();

指紋識別關鍵方法 authenticate

BiometricPrompt.authenticate(@NonNull CryptoObject crypto,
            @NonNull CancellationSignal cancel,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull AuthenticationCallback callback)

引數和6.0的差不多,

  • Executor executor (補充,是)

這個引數是 Android 9.0 Api BiometricPrompt.authenticate() 中的引數,是 @NonNull 的,作用與上個引數 Handler handler 類似,用來分發指紋識別的回呼事件,

當通過主執行緒進行分發時,可通過 Context#getMainExecutor() 傳參;

當通過共享執行緒池進行分發時,可通過 AsyncTask#THREAD_POOL_EXECUTOR 傳參,

本文相關的事例代碼可自行進行下載:GitHub - WCaiZhu/FingerprintRecognition: 有關指紋識別的工具包,適配6.0和9.0以上的安卓設備

可查看更多有關指紋的文章:

Android6.0指紋解鎖demo_小白的究極進化-CSDN博客

指紋登錄 - 徐繼收 - 博客園

Android開發學習—指紋識別系統的原理與使用_程式病毒小隊的博客-CSDN博客Android 指紋識別,提升APP用戶體驗,從這里開始_牛角尖-CSDN博客

轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/304358.html

標籤:其他

上一篇:C代碼如何跑起來(程式編譯和預處理)

下一篇:API 庫的檔案體系支持:主流編程語言的檔案設計

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【從零開始擼一個App】Dagger2

    Dagger2是一個IOC框架,一般用于Android平臺,第一次接觸的朋友,一定會被搞得暈頭轉向。它延續了Java平臺Spring框架代碼碎片化,注解滿天飛的傳統。嘗試將各處代碼片段串聯起來,理清思緒,真不是件容易的事。更不用說還有各版本細微的差別。 與Spring不同的是,Spring是通過反射 ......

    uj5u.com 2020-09-10 06:57:59 more
  • Flutter Weekly Issue 66

    新聞 Flutter 季度調研結果分享 教程 Flutter+FaaS一體化任務編排的思考與設計 詳解Dart中如何通過注解生成代碼 GitHub 用對了嗎?Flutter 團隊分享如何管理大型開源專案 插件 flutter-bubble-tab-indicator A Flutter librar ......

    uj5u.com 2020-09-10 06:58:52 more
  • Proguard 常用規則

    介紹 Proguard 入口,如何查看輸出,如何使用 keep 設定入口以及使用實體,如何配置壓縮,混淆,校驗等規則。

    ......

    uj5u.com 2020-09-10 06:59:00 more
  • Android 開發技術周報 Issue#292

    新聞 Android即將獲得類AirDrop功能:可向附近設備快速分享檔案 谷歌為安卓檔案管理應用引入可安全隱藏資料的Safe Folder功能 Android TV新主界面將顯示電影、電視節目和應用推薦內容 泄露的Android檔案暗示了傳說中的谷歌Pixel 5a與折疊屏新機 谷歌發布Andro ......

    uj5u.com 2020-09-10 07:00:37 more
  • AutoFitTextureView Error inflating class

    報錯: Binary XML file line #0: Binary XML file line #0: Error inflating class xxx.AutoFitTextureView 解決: <com.example.testy2.AutoFitTextureView android: ......

    uj5u.com 2020-09-10 07:00:41 more
  • 根據Uri,Cursor沒有獲取到對應的屬性

    Android: 背景:呼叫攝像頭,拍攝視頻,指定保存的地址,但是回傳的Cursor檔案,只有名稱和大小的屬性,沒有其他諸如時長,連ID屬性都沒有 使用 cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATIO ......

    uj5u.com 2020-09-10 07:00:44 more
  • Android連載29-持久化技術

    一、持久化技術 我們平時所使用的APP產生的資料,在記憶體中都是瞬時的,會隨著斷電、關機等丟失資料,因此android系統采用了持久化技術,用于存盤這些“瞬時”資料 持久化技術包括:檔案存盤、SharedPreference存盤以及資料庫存盤,還有更復雜的SD卡記憶體儲。 二、檔案存盤 最基本存盤方式, ......

    uj5u.com 2020-09-10 07:00:47 more
  • Android Camera2Video整合到自己專案里

    背景: Android專案里呼叫攝像頭拍攝視頻,原本使用的 MediaStore.ACTION_VIDEO_CAPTURE, 后來因專案需要,改成了camera2 1.Camera2Video 官方demo有點問題,下載后,不能直接整合到專案 問題1.多次拍攝視頻崩潰 問題2.雙擊record按鈕, ......

    uj5u.com 2020-09-10 07:00:50 more
  • Android 開發技術周報 Issue#293

    新聞 谷歌為Android TV開發者提供多種新功能 Android 11將自動填表功能整合到鍵盤輸入建議中 谷歌宣布Android Auto即將支持更多的導航和數字停車應用 谷歌Pixel 5只有XL版本 搭載驍龍765G且將比Pixel 4更便宜 [圖]Wear OS將迎來重磅更新:應用啟動時間 ......

    uj5u.com 2020-09-10 07:01:38 more
  • 海豚星空掃碼投屏 Android 接收端 SDK 集成 六步驟

    掃碼投屏,開放網路,獨占設備,不需要額外下載軟體,微信掃碼,發現設備。支持標準DLNA協議,支持倍速播放。視頻,音頻,圖片投屏。好點意思。還支持自定義基于 DLNA 擴展的操作動作。好像要收費,沒體驗。 這里簡單記錄一下集成程序。 一 跟目錄的build.gradle添加私有mevan倉庫 mave ......

    uj5u.com 2020-09-10 07:01:43 more
最新发布
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:40:31 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:40:11 more
  • 歡迎頁輪播影片

    如圖,引導開始,球從上落下,同時淡入文字,然后文字開始輪播,最后一頁時停止,點擊進入首頁。 在來看看效果圖。 重力球先不講,主要歡迎輪播簡單實作 首先新建一個類 TextTranslationXGuideView,用于影片展示 文本是類似的,最后會有個圖片箭頭影片,布局很簡單,就是一個 TextVi ......

    uj5u.com 2023-04-20 08:39:36 more
  • 【FAQ】關于華為推送服務因營銷訊息頻次管控導致服務通訊類訊息

    一. 問題描述 使用華為推送服務下發IM訊息時,下發訊息請求成功且code碼為80000000,但是手機總是收不到訊息; 在華為推送自助分析(Beta)平臺查看發現,訊息發送觸發了頻控。 二. 問題原因及背景 2023年1月05日起,華為推送服務對咨詢營銷類訊息做了單個設備每日推送數量上限管理,具體 ......

    uj5u.com 2023-04-20 08:39:13 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:16:23 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:16:15 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:15:46 more
  • iOS從UI記憶體地址到讀取成員變數(oc/swift)

    開發除錯時,我們發現bug時常首先是從UI顯示發現例外,下一步才會去定位UI相關連的資料的。XCode有給我們提供一系列debug工具,但是很多人可能還沒有形成一套穩定的除錯流程,因此本文嘗試解決這個問題,順便提出一個暴論:UI顯示例外問題只需要兩個步驟就能完成定位作業的80%: 定位例外 UI 組 ......

    uj5u.com 2023-04-19 09:14:53 more
  • FIDE重磅更新!性能飛躍!體驗有禮!

    FIDE 開發者工具重構升級啦!實作500%性能提升,誠邀體驗! 一直以來不少開發者朋友在社區反饋,在使用 FIDE 工具的程序中,時常會遇到諸如加載不及時、代碼預覽/渲染性能不如意的情況,十分影響開發體驗。 作為技術團隊,我們深知一件趁手的開發工具對開發者的重要性,因此,在2023年開年,FinC ......

    uj5u.com 2023-04-19 09:14:08 more
  • 游戲內嵌社區服務開放,助力開發者提升玩家互動與留存

    華為 HMS Core 游戲內嵌社區服務提供快速訪問華為游戲中心論壇能力,支持玩家直接在游戲內瀏覽帖子和交流互動,助力開發者擴展內容生產和觸達的場景。 一、為什么要游戲內嵌社區? 二、游戲內嵌社區的典型使用場景 1、游戲內打開論壇 您可以在游戲內繪制論壇入口,為玩家提供沉浸式發帖、瀏覽、點贊、回帖、 ......

    uj5u.com 2023-04-19 09:08:34 more