李忠丞 瀋陽大學學士,騰訊優測產品支撐組組長;2011年加入騰訊,專一移動終端開發,前後參與過騰訊微博研發以及手機QQ瀏覽器、Qzone、魅拍等產品的機型適配工做。android
快捷方式雖然看起來只是一個很小的功能點,可是他涉及到的機型適配問題不少。數據庫
快捷方式建立代碼:編程
ntent addShortCut = new Intent("com.android.launcher.action.INSTALL_SHORTCUT"); addShortCut.putExtra(Intent.EXTRA_SHORTCUT_NAME, title); // 不容許重複建立 addShortCut.putExtra("duplicate", false); addShortCut.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, icon); addShortCut.putExtra(Intent.EXTRA_SHORTCUT_INTENT, intent); sendBroadcast(addShortCut);
1 沒法建立快捷方式瀏覽器
愈來愈多的手機廠商取消了快捷方式的概念,致使咱們沒法經過代碼建立一個咱們須要的快捷方式,根據咱們所掌握的數據顯示,這樣的手機約佔 13%。markdown
2 重複建立快捷方式app
一般狀況下,咱們是不但願本身的快捷方式被重複建立:佈局
使用 addShortCut.putExtra(「duplicate」, false);方法就能達到目的,可是市面上的手機至少有 8%的手機即便設置了 DUPLICATE 爲 FALSE 仍是能夠重複建立快捷方式的。spa
表明手機品牌爲:華爲 中興 HTCcode
Android Launcher 源碼:orm
2.1 重複建立快捷方式的解決方案 V1.X
咱們最先使用的解決快捷方式重複建立的方法是:在建立快捷方式前先執行刪除操做,這種方式其實很聰明,由於即便是在快捷方式不存在的狀況下執行刪除操做也不會有任何異常,這樣看來問題解決地過輕鬆了,可是遺憾的是刪除快捷方式一樣存在適配問題,咱們掌握的數據顯示大約 21%的手機沒法正常刪除快捷方式。
另一種方法是:自行保存快捷方式的建立記錄,經過一個字段來記錄快捷方式是否已經建立過了,以此來決定是否建立新的快捷方式,這種作法也是由於出現快捷方式沒法刪除狀況後對解決方案進行了一個小的升級,雖然能夠解決問題,可是若是程序被清除了數據,那麼一切都亂了,仍是沒法完全的規避重複的問題。
2.2 重複建立快捷方式的解決方案 V2.X
遇到難解的問題仍是看看源碼吧,Android 的 Launcher 源碼在建立快捷方式的時候不只會判斷 duplicate 的值,還會在數據庫中查詢一下將要被建立的快捷方式是否已經存在,咱們也照作就 OK 了。
咱們注意到,查詢數據庫的時候訪問地址URI 是一個很重要的因素,問題是數據庫的URI比較多,Android 標準的URI 就有3 個:
2.2 版本之前的URI 是:content://com.android.launcher.settings/favorites?notify=true
2.2~4.3 版本的URI 是:content://com.android.launcher2.settings/favorites?notify=true
4.4 版本以上的目前都是:content://com.android.launcher3.settings/favorites?notify=true
不只僅Android 本身的Launcher 數據庫地址衆多,廠商本身定義的地址就更加豐富多彩,如OPPO R827T 的訪問URI 爲:content://com.oppo.launcher.settings /favorites?notify=true
HTC Z715e 的訪問地址爲:
content://com.htc.launcher.settings/favorites?notify=true
遠遠不止這些,還有不可勝數的第三方Launcher 應用,不少開發者也會修改數據庫訪問地址,目前僅咱們掌握的不一樣訪問地址就有多達40 種左右。
經過權限查詢URI:
經過數據庫的讀寫權限來查詢對應的URI 相信你們也不陌生,感受上像是找到了終極的解決方案,且看下去…
問題一:若是使用完整的權限進行查詢—權限衆多,咱們目前掌握的超過 50 種。
問題二:若是使用不完整的權限進行查詢(READ_SETTINGS)對應關係複雜,大約有 32%的手機會對應兩個以上的 URI。
例如:
GT-I8262D:
authority:com.sec.android.app.launcher.settings
ReadPermission:com.android.launcher.permission.READ_SETTINGS
authority:com.sec.android.app.launcher.settings.id
ReadPermission:com.android.launcher.permission.READ_SETTINGSLenovo A278t:
authority:com.aspire.mm.Settings ReadPermission:com.aspire.mm.permission.READ_SETTINGS
authority:com.huaqin.launcherEx.settings
ReadPermission:com.huaqin.launcherEx.permission.READ_SETTINGS
authority:com.huaqin.thememgr.Settings
ReadPermission:com.huaqin.thememgr.permission.READ_SETTINGS
1 Intent 調用手機內相機程序
若是咱們設置了照片的存儲路徑,那麼極可能會遇到一下三種問題:
問題一:onActivityResult 方法中的data 返回爲空(數據代表,93%的機型的data 將會是Null,因此若是咱們指定了路徑,就不要使用data 來獲取照片,起碼在使用前要作空判斷)
問題二:照片沒法存儲
若是自定義存儲路徑是/mnt/sdcard/lowry/,而手機SD 卡下在拍照前沒有名爲lowry 的文件夾,那麼部分手機拍照後圖片不會保存,致使咱們沒法得到照片,大多數手機的相機遇到文件夾不存在的狀況都會本身建立出不存在的文件夾,而個別手機卻不會建立,其表明機型爲:三星I825八、華爲H30-T00、紅米等。解決的方法就是在指定存儲路徑前先判斷路徑中的文件夾是否都存在,不存在先建立再調用相機。
問題三:照片能夠存儲,可是名字不對
file:///mnt/sdcard/123 1.jpg,因爲Uri 的fromFile 方法會將路徑中的空格用「%20」取代。其實對於大多數的手機這都不算事,手機在解析存儲路徑的時候都會將「%20」替換爲空格,這樣實際上最終的照片名字仍是咱們當初指定的名字:123 1.jpg,遺憾的是個別手機(如酷派7260)系統自帶的相機沒有將「%20」讀成空格,拍照後的照片的名字是123%201.jpg,咱們用路徑「file:///mnt/sdcard/123 1.jpg」能找到照片纔怪!!
總結:
(1)使用 onActivityResult 中的 intent(data)前要作空判斷。
(2)指定拍照路徑時,先檢查路徑中的文件夾是否都存在,不存在時先建立文件夾再調用相機拍照。
(3)指定拍照存儲路徑時,照片的命名中不要包含空格等特殊符號。
2 經過 Camera 的 open 方法調用手機攝像頭
2.1 連續自動對焦 crash
緣由:第一次對焦未結束,應用層又發起的第二次對焦,引發對焦失敗。
解決方案一:傳入 AutoFocusCallback
解決方案二:延時操做
解決方案三:異常捕獲
2.2 攝像頭個數判斷錯誤
現象:當咱們使用 Camera.getNumberOfCameras()方法檢測攝像頭數量時返回的結果不許確,若是咱們嘗試打開一個不存在的攝像頭確定會拋出異常,這也提醒咱們在開啓 Camera 攝像頭時須要加異常保護。
表明機型:聯想 278t 酷派 8022
2.3 閃光燈的判斷
咱們經常使用的判斷手機是否有閃光燈的方法應該有如下兩種:
判斷是否支持閃光燈方法一:使用getSupportedFlashModes 方法
判斷是否支持閃光燈方法二:經過PackageManager 判斷
方法一有 3.7%的機器結果錯誤,沒法準確地判斷出手機是否有閃光燈,主要的品牌包含:酷派、天語、聯想、三星等。
方法二有 9.7%的機器結果錯誤,主要品牌包含:VIVO、金立、酷派、天語、朵惟、三星等。咱們建議在判斷手機是否有閃光燈的時候將這兩種方法聯合使用,出現錯誤的機率將大大下降。
2.4 常亮狀態與其餘狀態間的切換
前提條件是咱們設置閃光燈爲常亮(Parameters.FLASH_MODE_TORCH),而且閃光燈成功常亮,此時咱們在設置閃光燈模式爲 Parameters.FLASH_MODE_AUTO 後閃光燈依然常亮,這樣的機型約佔熱門機型的12% ,遇到這種狀況咱們須要先設置閃光燈模式爲Parameters.FLASH_MODE_OFF 關閉閃光燈後再設置其餘模式。
2.5 釋放 Camera 後閃光燈依舊閃亮
既然開了,咱們就要負責關,說實話,之前這個問題根本不在個人考慮範內,由於咱們在使用 Camera 的時候都會在Activity 被銷燬或者暫停時釋放 Camera,這個時候不管閃光燈是什麼狀態,都會隨着 Camera 的釋放而關閉,直到我碰見了 OPPO R815T,個人世界觀發生了變化,這貨若是設置了閃光燈常亮,即便釋放了 Camera 閃光燈依舊穩穩地亮着,並且因爲Camera 被釋放掉了,你再也沒辦法關閉閃光燈了,關閉 App、卸載 App,你仍是扣電池關機吧…..因此,若是你的程序中有設置閃光燈爲常亮狀態的操做,建議在釋放 Camera 前先將閃光燈設置爲關閉(Parameters.FLASH_MODE_OFF)狀態。
2.6 CameraInfo 的另類狀況
官方文檔中有關於調整相機預覽角度的例子
在這個例子中CameraInfo 很是重要,最終的角度計算就是根據CameraInfo 中orientation 值獲得的,因此若是這個值不許確的話那麼咱們的角度就有可能出現錯誤。
VIVO V1 手機第一次咱們獲取CameraInfo 的orientation 值是90,而當執行了mCamera =Camera.open();以後再獲取CameraInfo 的orientation 值就是0,並且之後獲取的都是0 ,除非重啓手機。
不管是這款手機上的哪一個應用,只要執行了一次Camera.open()以後,其餘全部程序中獲取CameraInfo 的orientation 都是是0。
機自帶的相機卻能很好的使用反編譯系統相機後果真發現系統相機並無像官方給出的例子來進行角度的矯正。
解決方案:
雙卡的問題解決的基本思路:
1.推斷:手機內置的系統APP 均可以正常使用這些功能,所以確定存在廠商自定義API 來實現這些功能;
2.反編譯:Framework、系統APP、系統數據庫;
3.定位:TelephoneManager 擴展、SMSManager 擴展、電話服務擴展、短信服務擴展、數據
庫字段擴展。
說到UI 適配其實非常讓人頭疼,下面的圖片是某個產品爲了進行UI 適配所作的工做,能夠看出至關繁瑣。
除了分辨率的適配,有時候佈局文件中的某個標籤還會引發一些問題,咱們先看下面一段佈局代碼:
正確結果:
錯誤結果:
這就是由於Android3.0 一下版本在FrameLayout 中使用layout_marginTo 標籤必需要設置gravity 才能生效。
那麼若是解決這個問題呢:
在設置android:layout_marginTop 的組件中再設置一下android:layout_gravity=」top」
1 廠商的抽象方法
若是你須要實現InputConnection 接口,那麼你必定要注意下面這個很奇葩的異常:
反編譯了下此款手機的framework,發現廠商在InputConnection 接口中增長了一個抽象方法performYLPrivateCommand
2 距離傳感器
2.1 不一樣手機event.values[0]值簡直是變幻無窮
簡單說幾個有表明性的:
2.2 數值與遠近關係不統一
既然咱們是經過數值來判斷當前是否出於近耳狀態,那麼是否是應該這個數值的大小是有說道的,靠近時的數值小一點,遠離時的數值大一些,起碼我見過的99%的手機是這樣子的,可是就有幾款神經病手機(100W)恰恰是靠近時的數值比遠離時的數值大,這是個坑,開發者要注意~~!!
2.3 getMaximumRange 方法返回值不對
有一句API:
SensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY).getMaximumRange()文檔解釋這個應該獲取的是傳感器數值變化的最大範圍,好比若是靠近時的值是0,遠離時的值是1,那麼getMaximumRange()的值應該是1 纔不會影響咱們的判斷,我這裏僅僅是從API 角度和咱們平常的使用習慣來講的,若是不是這樣的規律,就會對咱們的編程形成麻煩。
酷派5890 手機:變化的數值爲(3,5),getMaximumRange()的值爲10;
華爲Y320-T00 手機,變化的數值爲(0,10),getMaximumRange()的值爲20;
中興U930HD 手機,變化的數值爲(3,100),getMaximumRange()的值爲1023;
Bugly是騰訊內部產品質量監控平臺的外發版本,其主要功能是App發佈之後,對用戶側發生的Crash以及卡頓現象進行監控並上報,讓開發同窗能夠第一時間瞭解到App的質量狀況,及時機型修改。目前騰訊內部全部的產品,均在使用其進行線上產品的崩潰監控。