最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android bug最近遇到的幾個坑解決分享

 更新時間:2022年12月13日 09:05:21   作者:leobert-lan  
這篇文章主要為大家介紹了Android bug最近遇到的幾個坑解決分享,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

前言

6-7月的事情著實有點多。沒有清風亦沒有鮮花,連蟬都熱到燥不動了,人自然也變得慵懶了許多。

月頭計劃和諸君探討下Compose(Compose-Desktop)和MVI實際投產后的感受,眼看即將到月底,低頭看著才寫一半的草稿,沉默良久,大抵這個月是沒有希望成稿了。

終究,只能挑一些最近遇到的問題寫一寫,欺騙自己還未曾擺爛。

Android R、S中的外部文件管理權限

想來是舒適太久了,目前負責的核心項目均是面向特定Android-Pad開發(fā)的,在 Android 9 已經躺了一年,已經快忘記了 適配 這一祖?zhèn)靼ぁ?/p>

但還有部分即將推出的項目是面向普通用戶的,順便談一談這個 老問題

Android 10 中提出了分區(qū)存儲,對于外部存儲空間的讀寫,除了需要處理FileProvider外,還需要配置 requestLegacyExternalStorage

Android R、S 中,進行了更嚴格的限制,需要獲取完整的外部存儲控制權限。

作者按:筆者負責的項目受技術之外因素的影響,改變現(xiàn)有的文件存儲路徑的阻力非常大

判斷與申請完全的控制權限

補充聲明權限

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

那么,相關權限如下:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>

并且需要運行時動態(tài)獲取權限,關鍵代碼如下:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
    if (!Environment.isExternalStorageManager()) {
        //略去引導彈窗等相關交互邏輯
        startActivityForResult(Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION), REQ_CODE_FILE_MANAGE)
        return
    }
}
// do something

可以結合 ActivityResultContracts 改造 onActivityResult,不再贅述。

用戶對軟件授予權限后可讀寫文件。

如何快速改造

隨著Compose跨平臺技術越來越熱,將應用的業(yè)務在多個平臺上復用也越發(fā)有價值,而平臺的差異性內容應當在平臺內部解決。

那么 如何在不修改Presenter/ViewModel 和 Model層的前提下,便捷的解決此類適配問題 越發(fā)具有價值。

當然,此類問題的解決不能脫離實際空談,便不做具體展開。目前在項目中先運用了 Proxy 方式,對業(yè)務層追加了前置邏輯,進行了簡單處理。

我已經設想了一個框架,并非PermissionX之類處理Android動態(tài)權限的框架,有后續(xù)實質進展后再與諸君分享。

藍牙居然搜索不到設備

如果直接適配Android 12,大概率不會出現(xiàn)該問題(未經過大量rom驗證),target是低版本,以往的業(yè)務代碼不到位就有可能受到影響

未適配Android 12 藍牙權限的應用,在部分手機上發(fā)現(xiàn)未打開 "訪問我的位置信息" 時(不是定位權限?。。?,會導致搜索不到藍牙設備。大抵是ROM廠商的杰作。

參考地圖類SDK的操作,增加以下檢測代碼:

LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
    //引導用戶開啟定位:Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)
}

在 target Android12 中:

  • 請求精確位置,需同時申請 ACCESS_FINE_LOCATION 和 ACCESS_COARSE_LOCATION 權限
  • (動態(tài))申請藍牙相關權限時,不再需要申請設備位置信息相關權限

理論上不需要再加這一檢測,但仍需經過大量ROM測試。建議保留該段檢測邏輯。

一個高star庫中的I/O和多線程的綜合性問題

前幾日和好友閑聊時,好友提到他們的項目中使用了一個開源的下載庫 Aria,但時不時會出現(xiàn)下載圖片失敗的問題,實質是庫的bug。

閱讀源碼后感到問題出在細節(jié)知識上,本篇也需要水一下字數(shù),索性拿來討論一二。

庫中運用到的技術:

  • 多線程&鎖
  • IO
  • Android的Handler

其中,多線程和鎖的知識本篇不談,我亦寫有相關系列;庫作者使用Android中的Handler簡化多線程間的通信,也不再展開;IO部分系統(tǒng)展開也很長,我已有系列文章計劃,本篇結合問題簡單談一談。

和文件服務器對比,移動端的文件上傳下載并發(fā)量很小,其速度制約一般在于:服務器單連接流量限制,網(wǎng)絡條件。

對于單個文件采用多線程方式上傳、下載,只能突破 單連接流量限制,以充分使用網(wǎng)絡資源。多個文件并行上下載的產品意義遠大于充分吃掉網(wǎng)絡帶寬資源。

注意:上下載的高帶寬占用一定程度上會影響其他網(wǎng)絡層業(yè)務

一般對于下載而言,使用多線程時用常規(guī)的 "碎文件合并" 的思路即可。用 RandomAccessFile并不是一個好主意。

多線程寫RandomAccessFile并非一件很美好的事情,以后的文章中細聊

在使用Java經典IO時,使用Buffer減少IO次數(shù)可以獲得很好的性能提升,需要注意及時 flush,該庫中用Buffer設計對 RandomAccessFile 進行了一層封裝。想來也是源自三方庫.

將部分代碼簡化后類似如下代碼:

class Demo {
    @Test
    fun mockDownload() {
        Looper.prepare()
        val appContext = InstrumentationRegistry.getInstrumentation().targetContext
        val file = File(appContext.cacheDir, "testtmp")
        if (file.exists()) {
            file.delete()
        }
        file.createNewFile()
        assertEquals(0, file.length())
        val data = "hello".encodeToByteArray()
        val bFile = BufferedRandomAccessFile(file, "rwd", 1024)
        val handler = object : Handler(Looper.myLooper()) {
            override fun handleMessage(msg: Message?) {
                super.handleMessage(msg)
                //模擬文件合并線程,僅斷言文件大小
                if (msg?.what == 1) {
                    assertEquals(data.size.toLong(), file.length())
                    Looper.myLooper()?.quit()
                }
            }
        }
        //模擬下載線程
        thread(priority = 1) {
            val ins = ByteArrayInputStream(data)
            try {
                val buffer = ByteArray(1024)
                var len: Int
                while (ins.read(buffer).also { len = it } != -1) {
                    bFile.write(buffer, 0, len)
                }
                //模擬下載完成消息
                handler.sendEmptyMessage(1)
//                Thread.yield() -- 模擬一下線程被切換或者因為鎖導致的同步
            } finally {
                ins.close()
//                bFile.flush() will be invoked in close
                bFile.close()
            }
        }
        Looper.loop()
    }
}

觀察這段代碼可以發(fā)現(xiàn),存在不安全因素:最后一個buffer塊的內容大小未必是1024,需等到 bFile.close()時方可寫入文件。

雖然 handler.sendEmptyMessage(1) 發(fā)送的消息會被異步執(zhí)行,但并不意味著 bFile.close() 一定會先執(zhí)行。鎖、AQS、系統(tǒng)線程調度等均可能會導致該問題。

以上就是Android bug最近遇到的幾個坑解決分享的詳細內容,更多關于Android bug解決的資料請關注腳本之家其它相關文章!

相關文章

最新評論

灵丘县| 霍山县| 乐都县| 友谊县| 阿坝县| 鹤岗市| 定安县| 洪泽县| 平湖市| 娄底市| 定兴县| 湘西| 枣庄市| 白水县| 屯留县| 玉环县| 方城县| 赣州市| 武冈市| 德州市| 娄底市| 府谷县| 勐海县| 鄯善县| 轮台县| 大竹县| 汉川市| 吉水县| 阿合奇县| 西青区| 广南县| 炎陵县| 保德县| 府谷县| 兖州市| 高平市| 孝昌县| 塘沽区| 安徽省| 阳原县| 新乡市|