Android開(kāi)發(fā)需要注意的坑

背景
此文純粹總結(jié)開(kāi)發(fā)Android以來(lái)遇到的一些坑,一來(lái)為了防止再次掉坑,二來(lái)是希望后面的朋友能躲開(kāi)這些坑。

包名重復(fù)問(wèn)題
由于Google Palyer沒(méi)有在中國(guó)登陸,中國(guó)存在有非常多的Android應(yīng)用商城,而且這些商城并沒(méi)有聯(lián)合起來(lái)對(duì)APP包名進(jìn)行檢測(cè),所以你APP中使用的包名很有可能會(huì)跟別人的APP重復(fù)。那么小明手機(jī)裝了別人的應(yīng)用,就裝不上你的應(yīng)用了。
建議:
1.包名定義要有一定的技術(shù),盡量避免太容易重復(fù)的包名,如:com.digital.home。
2.要確定包名前,可以將應(yīng)用發(fā)到一些測(cè)試網(wǎng)站去測(cè)試,比如testin,它會(huì)將的你APP安裝到20臺(tái)機(jī),看能否全部正常安裝。

textSize單位問(wèn)題
Android Studio提示所有textSize的單位都應(yīng)該使用sp,因?yàn)檫@樣該text就能夠隨用戶(hù)在系統(tǒng)setting里設(shè)置的字體大小的改變而改變。那么如果你使用了sp作單位,那么建議你調(diào)整setting字體至最大或最小后,看UI是否還能正常顯示。我個(gè)人使用了不規(guī)范的dp作為單位。

小米手機(jī)圖標(biāo)異常問(wèn)題
在別的手機(jī)顯示沒(méi)有這問(wèn)題,在小米手機(jī)顯示就有下圖的問(wèn)題,解壓apk包也沒(méi)發(fā)現(xiàn)該圖標(biāo)。其實(shí)這是小米手機(jī)的BUG,解決方法是將APP上傳至小米應(yīng)用商城,它會(huì)要求你上傳一整套桌面圖標(biāo)icon,據(jù)說(shuō)現(xiàn)在小米應(yīng)用商城已經(jīng)去掉了這部分功能。

圖標(biāo)顯示異常

部分手機(jī)因權(quán)限問(wèn)題無(wú)法安裝應(yīng)用問(wèn)題
一時(shí)記不起是什么手機(jī),大概是中興還是樂(lè)視手機(jī),只需要在AndroidManifest.xml里增加一個(gè)自定義權(quán)限就可以了。

<permission android:name="cus.permission.com.xxx.xxx"
            android:protectionLevel="normal"/>

魅藍(lán)手機(jī)EditText的enabled屬性無(wú)用問(wèn)題
在xml里面讓EditText不可編輯狀態(tài),是設(shè)置android:enabled="false",但是發(fā)現(xiàn)在魅藍(lán)note2這樣設(shè)置后還是可以編輯,再加上下面這句就可以了。

mPhoneNumEt.setEnabled(false);

百度更新與360更新沖突問(wèn)題
之前應(yīng)用集成了百度更新與360更新,然后上傳至360后臺(tái)發(fā)布,但是審核不通過(guò),解決方法只需要把AndroidManifest.xml里百度相關(guān)的xml屏蔽再打包即可。

集成騰訊X5 WebKit無(wú)法讀取SD卡html文件問(wèn)題
將html文件放到/data/data/com.example.demo/files/ 里面,結(jié)果發(fā)現(xiàn)X5根本無(wú)法讀取,后來(lái)通過(guò)跟騰訊工作人員溝通,原來(lái)舊版本的X5只允許讀取/sdcard 和私有目錄下的/data/data/com.example.demo/files/public目錄,其他目錄的調(diào)用都被禁止了。
我手機(jī)上的X5版本是2258,而新的版本如3321已經(jīng)不再限制了,所以要兼容低版本的X5內(nèi)核,還是需要把文件放在public目錄下。更詳細(xì)的集成方案請(qǐng)閱讀《集成第三方組件--Android APP集成騰訊X5 WebKit》

AsyncTask
AsyncTask只能執(zhí)行簡(jiǎn)短任務(wù),執(zhí)行長(zhǎng)時(shí)間耗時(shí)任務(wù)會(huì)阻塞其他使用AsyncTask的任務(wù)。在項(xiàng)目中慎用,我踩過(guò)關(guān)于它的坑是在輪播圖里使用了它,導(dǎo)致其他AsyncTask阻塞,不能正常使用。比如集成七魚(yú)客服SDK無(wú)法獲取相冊(cè)圖片,比如獲取短信驗(yàn)證碼倒計(jì)時(shí)無(wú)法正常倒計(jì)時(shí)。詳細(xì)可參考:AsyncTask 使用和缺陷

集成個(gè)推SDK的坑
個(gè)推最近推出了2.9.0版本的SDK,集成后打包apk文件,發(fā)現(xiàn)Android 5.0以上的系統(tǒng)都無(wú)法安裝,顯示“應(yīng)用未安裝”,只能使用之前的2.8.1.0的版本,這個(gè)問(wèn)題在他們Demo也已經(jīng)驗(yàn)證過(guò),各位要注意。

簽名問(wèn)題
生成簽名文件xxx.jks,兩個(gè)StorePassword和KeyPassword都沒(méi)有錯(cuò),但是還是提示:Cannot recover key,后來(lái)刪掉xxx.jks ,重新生成,并設(shè)置StorePassword和KeyPassword為同一個(gè)密碼,然后就可以了。

奇葩所在:
沒(méi)來(lái)得及分析這是為什么,因?yàn)槲椰F(xiàn)在用的其他簽名文件兩個(gè)密碼不一致也沒(méi)問(wèn)題。后面我再次嘗試使用不一樣的密碼,發(fā)覺(jué)原理問(wèn)題不存在了。

可能的原因:
1.是IDE的BUG,重啟IDE就能搞定;

WebView加載htm影響原生頁(yè)面工作
公司項(xiàng)目使用HyBrid方式開(kāi)發(fā),直到有個(gè)頁(yè)面需要使用動(dòng)畫(huà)、設(shè)置View顯示隱藏、設(shè)置View的高度、刷新GridView數(shù)據(jù),但是發(fā)現(xiàn)加載a.html后這些功能全部失效或異常了,而選擇加載b.html就沒(méi)問(wèn)題,而且這個(gè)只發(fā)生在我的4.3手機(jī)上。

奇葩所在:
不知道確切原因,問(wèn)題還沒(méi)解決。

可能原因:
1.htm某些功能影響了原生頁(yè)面?
2.加載這個(gè)頁(yè)面是否需要開(kāi)啟某些功能?

WebView加載html頁(yè)面后,部分手機(jī)顯示頁(yè)面過(guò)大
兩臺(tái)手機(jī)加載同一個(gè)html頁(yè)面,一個(gè)正常顯示,另一個(gè)頁(yè)面顯示不全,可以左右滑動(dòng),這個(gè)問(wèn)題已經(jīng)解決,問(wèn)題是另一臺(tái)手機(jī)調(diào)整了系統(tǒng)字體大小導(dǎo)致。解決方法是設(shè)置WebView顯示為normal字體大小,代碼如下:

webSetting.setTextSize(WebSettings.TextSize.NORMAL);
webSetting.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);

提示“應(yīng)用未安裝”
手機(jī)連接usb線(xiàn)的時(shí)候可以安裝,但是下載apk安裝卻提示“應(yīng)用未安裝”,今天也發(fā)現(xiàn)支付寶出現(xiàn)了這個(gè)問(wèn)題。原因是我們打包的apk不完整或路徑有問(wèn)題導(dǎo)致,我這里發(fā)現(xiàn)的問(wèn)題是在使用Gradle打包.so文件打包方式不對(duì),最后參考http://blog.csdn.net/wulianghuan/article/details/44567001。

ListView中的CheckBox
若在ListView的Item中有CheckBox,而這個(gè)時(shí)候在Adapter中我們又設(shè)置了各個(gè)Item中OnCheckedChangeListener,那么在ListView滑動(dòng)過(guò)程中,或者加載過(guò)程中會(huì)不斷調(diào)用這個(gè)方法,正確的寫(xiě)法是:

holder.cbItem.setOnCheckedChangeListener(null); //設(shè)置為空
if (mList.get(i).is_select()) { //設(shè)置其狀態(tài)
     holder.cbItem.setChecked(true);
} else {
     holder.cbItem.setChecked(false);
} 
//設(shè)置狀態(tài)變化監(jiān)聽(tīng)事件
holder.cbItem.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
     @Override
     public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
           mItemContentClickListener.selectGoods(i, isChecked);
     }
});

需要注意的setOnCheckedChangeListener方法
該方法不僅在我們點(diǎn)擊的時(shí)候會(huì)調(diào)用,而且在調(diào)用setChecked的時(shí)候也會(huì)被調(diào)用,正如其名字的意思,但是我們?cè)陂_(kāi)發(fā)中經(jīng)常會(huì)忽略掉setChecked會(huì)調(diào)用該方法的事情,導(dǎo)致系統(tǒng)出現(xiàn)Bug。

mSelectAll.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
     @Override
     public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
         showLog("setOnCheckedChangeListener");
     }
});

如果只是需要在點(diǎn)擊的時(shí)候回調(diào),那還是設(shè)置setOnClickListener監(jiān)聽(tīng)吧。

Adapter里數(shù)據(jù)引用改變導(dǎo)致數(shù)據(jù)不改變的問(wèn)題
我們通過(guò)初始化Adapter設(shè)置mGoodList數(shù)據(jù)在ListView中顯示:

GoodsListAdapter goodsListAdapter=new GoodsListAdapter(this,mGoodsList);
mListView.setAdapter(goodsListAdapter);

當(dāng)我們數(shù)據(jù)改變時(shí),容易犯一下錯(cuò)誤:

mGoodsList=mOtherList;
goodsListAdapter.notifyDataSetChanged();

正確的應(yīng)該是:

mGoodsList.clear();
mGoodsList.addAll(mOtherList);
goodsListAdapter.notifyDataSetChanged();

原因是在我們new GoodsListAdapter(...)已將mGoodsList的引用傳遞給Adapter,如果mGoodsList=mOtherList這種方法給mGoodsList賦值是不成功的,賦給mGoodsList的是新的引用,但Adapter卻還保留原來(lái)的引用。

SQLite里存儲(chǔ)INTEGER數(shù)據(jù)
在創(chuàng)建表時(shí),將某一字段類(lèi)型設(shè)置為INTEGER,如果存儲(chǔ)00311104035001這樣的數(shù)據(jù),SQLite真正存儲(chǔ)的值會(huì)變?yōu)?11104035001。若要避免這種錯(cuò)誤,可選擇VARCHAR類(lèi)型。

APP升級(jí)要留一條后路
即強(qiáng)制升級(jí),因?yàn)殚_(kāi)發(fā)中總會(huì)遇到這種需求;

浮點(diǎn)數(shù)或雙精度計(jì)算時(shí)要考慮保留小數(shù)點(diǎn)后的位數(shù)
之前做計(jì)算時(shí)沒(méi)有考慮這個(gè),導(dǎo)致有些計(jì)算的結(jié)果是個(gè)無(wú)線(xiàn)循環(huán)小數(shù),如:128.6999999...,以下是個(gè)方法:

public String getResult(double num){
    BigDecimal input = new BigDecimal(num);
    double result = input.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
    return String.valueOf(result);
}

ListView設(shè)置setOnItemClickListener點(diǎn)擊沒(méi)反應(yīng)
問(wèn)題一般是由于ListView中的ItemView里有Button、Checkbox、ImageView等控件,導(dǎo)致點(diǎn)擊ItemView時(shí)焦點(diǎn)其他控件攔截了,要解決此問(wèn)題,只需要在控件上設(shè)置android:focusable="false"。

DatePickerDialog的顯示的問(wèn)題
我們輸入的對(duì)話(huà)框初始日期是2017-4-2,但是顯示的對(duì)話(huà)框卻是2017-5-2,而選出的日期是4月,這明顯會(huì)誤導(dǎo)用戶(hù)。所以我們需要做些處理,在初始的月份-1,在回調(diào)的結(jié)果里+1,這就能達(dá)到我們想要的效果。

int yearParam=2017;
int monthParam=4;
int dayParam=2;

new DatePickerDialog(MainActivity.this, new DatePickerDialog.OnDateSetListener() {
       @Override
       public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
             String result = year + "-" + (monthOfYear+1) + "-" + dayOfMonth;
             textView.setText(result);
        }
}, yearParam, monthParam-1, dayParam).show();

待續(xù)......

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容