編輯:關於android開發
一、鎖卡背景介紹
鎖卡即SIMLock,當手機開機啟動或者插入SIM卡時,手機modem側預置在NV項中的配置信息會與SIM卡中的信息做比對,檢測是否匹配。若匹配,則SIM卡可以正常使用。若不匹配,則SIM卡相關功能均無法正常使用,例如撥打電話、發送短信及上網等;或者是只能注冊2G網,不能注冊4G。
鎖卡的目的:一些運營商會要求控制某一類卡的使用,從而保護自己的利益(運營商定制機)
SIMLock鎖和圖案鎖,數字密碼鎖,PIN碼鎖,PUK鎖一樣,是Keyguard模塊中的一種鎖。
二、鎖卡的需求
鎖卡的需求方式有7種之多,常見的有NP鎖,NS鎖,CP鎖,SP鎖等
從安卓機器來看,目前最常用的是SP鎖(MCC/MNC),本文將解析SP鎖的加鎖流程
三、鎖卡流程解析
1.首先modem側檢測SIM卡的配置信息並與之作比對,若匹配則繼續加載SIM卡,若不匹配,則上報加鎖信息
2.RIL層檢測到modem上報的加鎖信息,然後發送給framework層,最終在AP層監測到事件:
3.AP層顯示出鎖卡界面,要求用戶輸入解鎖碼進行解鎖
四、相關流程圖
1.加鎖流程圖
2.解鎖流程圖
五、代碼解析
MTK平台已經支持SIMLock功能,但只能在代碼中寫固定的MCC/MNC,不能靈活配置。即一套代碼只能對應一套對應的鎖卡配置信息,對於手機廠商來說,顯然不滿足需求,發貨國家遍布全球,鎖卡配置信息均不同,代碼版本太多無法管理,故肯定要廢棄MTK的這套SIMLock功能。
(1)modem側客制化
涉及的代碼文件:
custom/modem/common/ps/custom_nvram_extra.c custom/modem/common/ps/customer_at_command.c custom/service/nvram/custom_nvram_sec.c custom/service/nvram/custom_nvram_sec.h interface/service/nvram/nvram_data_items.h service/nvram/src/nvram_factory_config.c service/nvram/src/nvram_main.c
a.擴展鎖卡配置信息的組數
custom_nvram_sec.h
#define SML_MAX_SUPPORT_CAT_N 50
初始化數組的時候,需要添加對應的默認配置信息
const nvram_sml_context_struct NVRAM_EF_SML_DEFAULT = { SML_MAGIC_HEAD_VALUE, {{SML_STATE_UNLOCK,SML_RETRY_COUNT_N_CAT,0,0}, /* Category N */ {SML_STATE_UNLOCK,SML_RETRY_COUNT_NS_CAT ,0,0}, /* Category NS */ {SML_STATE_UNLOCK,SML_RETRY_COUNT_SP_CAT ,0,0}, /* Category SP */ {SML_STATE_UNLOCK,SML_RETRY_COUNT_C_CAT ,0,0}, /* Category C */ {SML_STATE_UNLOCK,SML_RETRY_COUNT_SIM_CAT ,0,0}, /* Category SIM */ {SML_STATE_UNLOCK,SML_RETRY_COUNT_NS_CAT ,0,0}, /* Link NS-SP */ {SML_STATE_UNLOCK,SML_RETRY_COUNT_C_CAT ,0,0}}, /* Link SIM-C */ {{SML_KEY_SET,{0x21,0x43,0x65,0x87,0xFF,0xFF,0xFF,0xFF}}, {SML_KEY_SET,{0x65,0x87,0x21,0x43,0xFF,0xFF,0xFF,0xFF}}, {SML_KEY_SET,{0x11,0x22,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}}, {SML_KEY_EMPTY,{0x33,0x44,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}}, {SML_KEY_EMPTY,{0x55,0x66,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}}, {SML_KEY_SET,{0x77,0x88,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}}, {SML_KEY_SET,{0x99,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}}}, /* Category N code */ {0x73,0x00,0x1F,0x73,0x00,0x2F,0x73,0x00,0x3F,0x73,0x00,0x4F,0x73,0x00,0x5F, 0x73,0x00,0x6F,0x73,0x00,0x7F,0x73,0x00,0x8F,0x73,0x00,0x9F,0x73,0x01,0x0F, 0x73,0x01,0x1F,0x73,0x09,0x9F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00}, /* Category NS code */ {0xc2,0xc2,0xc2,0xc2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00}, /* Category SP code */ {0xc3,0xc3,0xc3,0xc3,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00}, /* Category C code */ {0xc4,0xc4,0xc4,0xc4,0xc4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00}, /* Category SIM code */ {0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xc5,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* Link Category NS-SP */ {0xc6,0xc6,0xc6,0xc6,0xc6,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00}, /* Link Category SIM-C */ {0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7,0xc7, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, {0xFF,0xFF}, SML_MAGIC_TAIL_VALUE };
b.修改剩余解鎖次數
custom_nvram_sec.h
#define SML_MAX_RETRY_COUNT 10
c.擴展客制化的鎖卡NV項
例如MTK源生的鎖卡NV項已經可以通過工具查看及修改,這樣鎖卡就容易被破解。客制化自己的鎖卡NV項,即使MTK源生的被破解了,SIMLock功能依舊正常工作。
不過從Android 6.0來看,MTK已經在modem側做了處理,使用工具無法查看及修改該NV項了。
(1)先定義NV項
(2)對該NV項進行對應的初始化,參考源生的即可
d.擴展鎖卡的特殊需求(關聯鎖卡等)
由於源生的AT指令不能查詢鎖卡狀態信息,可以通過擴展AT指令來實現
如下代碼為擴展的AT+QSIM1的指令,查詢的信息包括鎖卡狀態,鎖卡配置信息,剩余次數等
if (strcmp(cmd_name, "QSIM1") == 0) { extern void simlock_query_sml_info(kal_uint8 sim_id, sml_context_struct* sml_static_buffer); char info_buffer[MAX_UART_LEN+1]; int NumOfPlmn,i; int isLocked = -1; sml_context_struct sml_static_buffer; memset(&sml_static_buffer,0x00,sizeof(sml_context_struct)); simlock_query_sml_info(1, &sml_static_buffer); kal_prompt_trace(MOD_SIM, "[sim1]: receive full_cmd_string =%s", full_cmd_string); sml_cat_enum cat = 0xff; for(cat = SML_CAT_N; cat < SML_CAT_SIZE; cat++) { if(sml_static_buffer.cat[cat].state == 0x01) { isLocked = 1; break; } } if(isLocked == 1) { NumOfPlmn = sml_static_buffer.cat[cat].num; NumOfPlmn = 1; sprintf(info_buffer, "+QSIM1:%02x;",sml_static_buffer.cat[cat].state); sprintf(info_buffer+strlen(info_buffer), "%02x;",NumOfPlmn); //#define SML_SIZE_OF_CAT_N 3 /* MCC/MNC */ //#define SML_SIZE_OF_CAT_NS 4 /* MCC/MNC + HLR */ //#define SML_SIZE_OF_CAT_SP 4 /* MCC/MNC + GID1 */ //#define SML_SIZE_OF_CAT_C 5 /* MCC/MNC + GID1 + GID2 */ //#define SML_SIZE_OF_CAT_SIM 8 /* IMSI */ //#define SML_SIZE_OF_LINK_NS_SP 5 /* MCC/MNC + HLR+ GID1 */ //#define SML_SIZE_OF_LINK_SIM_C 10 /* IMSI + GID1 + GID2 */ if(cat == SML_CAT_N) { for(i = 0; i < NumOfPlmn*SML_SIZE_OF_CAT_N; i=i+SML_SIZE_OF_CAT_N) { sprintf(info_buffer+strlen(info_buffer), "%02x%02x%02x;",sml_static_buffer.code_cat_n[i], sml_static_buffer.code_cat_n[i + 1],sml_static_buffer.code_cat_n[i + 2]); } //sprintf(info_buffer+strlen(info_buffer), "%02x%02x%02x%02x",sml_static_buffer.key[cat].key[4], // sml_static_buffer.key[cat].key[5],sml_static_buffer.key[cat].key[6],sml_static_buffer.key[cat].key[7]); //kal_prompt_trace(MOD_SIM, " receive cmd =%s ; flag is %x ", cmd_name, read_buffer); } else if(cat == SML_CAT_NS) { for(i = 0; i < NumOfPlmn*SML_SIZE_OF_CAT_NS; i=i+SML_SIZE_OF_CAT_NS) { sprintf(info_buffer+strlen(info_buffer), "%02x%02x%02x%02x;",sml_static_buffer.code_cat_ns[i], sml_static_buffer.code_cat_ns[i + 1],sml_static_buffer.code_cat_ns[i + 2],sml_static_buffer.code_cat_ns[i + 3]); } } else if(cat == SML_CAT_SP) { for(i = 0; i < NumOfPlmn*SML_SIZE_OF_CAT_SP; i=i+SML_SIZE_OF_CAT_SP) { sprintf(info_buffer+strlen(info_buffer), "%02x%02x%02x%02x;",sml_static_buffer.code_cat_sp[i], sml_static_buffer.code_cat_sp[i + 1],sml_static_buffer.code_cat_sp[i + 2],sml_static_buffer.code_cat_sp[i + 3]); } } else if(cat == SML_CAT_C) { for(i = 0; i < NumOfPlmn*SML_SIZE_OF_CAT_C; i=i+SML_SIZE_OF_CAT_C) { sprintf(info_buffer+strlen(info_buffer), "%02x%02x%02x%02x",sml_static_buffer.code_cat_c[i], sml_static_buffer.code_cat_c[i + 1],sml_static_buffer.code_cat_c[i + 2],sml_static_buffer.code_cat_c[i + 3]); sprintf(info_buffer+strlen(info_buffer), "%02x;",sml_static_buffer.code_cat_c[i + 4]); } } else if(cat == SML_CAT_SIM) { for(i = 0; i < NumOfPlmn*SML_SIZE_OF_CAT_SIM; i=i+SML_SIZE_OF_CAT_SIM) { sprintf(info_buffer+strlen(info_buffer), "%02x%02x%02x%02x",sml_static_buffer.code_cat_sim[i], sml_static_buffer.code_cat_sim[i + 1],sml_static_buffer.code_cat_sim[i + 2],sml_static_buffer.code_cat_sim[i + 3]); sprintf(info_buffer+strlen(info_buffer), "%02x%02x%02x%02x;",sml_static_buffer.code_cat_sim[i + 4], sml_static_buffer.code_cat_sim[i + 5],sml_static_buffer.code_cat_sim[i + 6], sml_static_buffer.code_cat_sim[i + 7]); } } else if(cat == SML_CAT_NS_SP) { for(i = 0; i < NumOfPlmn*SML_SIZE_OF_LINK_NS_SP; i=i+SML_SIZE_OF_LINK_NS_SP) { sprintf(info_buffer+strlen(info_buffer), "%02x%02x%02x%02x",sml_static_buffer.code_cat_ns_sp[i], sml_static_buffer.code_cat_ns_sp[i + 1],sml_static_buffer.code_cat_ns_sp[i + 2],sml_static_buffer.code_cat_ns_sp[i + 3]); sprintf(info_buffer+strlen(info_buffer), "%02x;",sml_static_buffer.code_cat_ns_sp[i + 4]); } } else if(cat == SML_CAT_SIM_C) { for(i = 0; i < NumOfPlmn*SML_SIZE_OF_LINK_SIM_C; i=i+SML_SIZE_OF_LINK_SIM_C) { sprintf(info_buffer+strlen(info_buffer), "%02x%02x%02x%02x",sml_static_buffer.code_cat_sim_c[i], sml_static_buffer.code_cat_sim_c[i + 1],sml_static_buffer.code_cat_sim_c[i + 2], sml_static_buffer.code_cat_sim_c[i + 3]); sprintf(info_buffer+strlen(info_buffer), "%02x%02x%02x%02x",sml_static_buffer.code_cat_sim_c[i + 4], sml_static_buffer.code_cat_sim_c[i + 5],sml_static_buffer.code_cat_sim_c[i + 6], sml_static_buffer.code_cat_sim_c[i + 7]); sprintf(info_buffer+strlen(info_buffer), "%02x%02x;",sml_static_buffer.code_cat_sim_c[i + 8], sml_static_buffer.code_cat_sim_c[i + 9]); } } sprintf(info_buffer+strlen(info_buffer), "%02x%02x%02x%02x",sml_static_buffer.key[cat].key[0], sml_static_buffer.key[cat].key[1],sml_static_buffer.key[cat].key[2],sml_static_buffer.key[cat].key[3]); sprintf(info_buffer+strlen(info_buffer), "%02x%02x%02x%02x;",sml_static_buffer.key[cat].key[4], sml_static_buffer.key[cat].key[5],sml_static_buffer.key[cat].key[6],sml_static_buffer.key[cat].key[7]); sprintf(info_buffer+strlen(info_buffer), "%02x;",sml_static_buffer.cat[cat].retry_count); sprintf(info_buffer+strlen(info_buffer), "%02x;",cat); } else { sprintf(info_buffer, "+QSIM1:%02x;",0x00); } //kal_prompt_trace(MOD_NVRAM, "[sim1]: info_buffer is === >> %s", info_buffer); rmmi_write_to_uart((kal_uint8*)info_buffer, strlen(info_buffer), KAL_FALSE); sprintf(buffer, "OK"); rmmi_write_to_uart((kal_uint8*)buffer, strlen(buffer), KAL_TRUE); return KAL_TRUE; }
(2)AP側客制化
SIMLock客制化工作量主要集中在modem側,AP側主要為界面顯示及AT指令的交互
a.AT指令的交互
查詢SIM卡狀態
查詢鎖卡狀態信息:是否鎖卡,鎖卡的配置信息(MCC/MNC),解鎖剩余次數等
發送PASSWORD到RIL側,解析解鎖是否成功的返回信息
b.用戶界面的顯示
提示用戶輸入解鎖碼
提示剩余解鎖次數
提示剩余時間可以繼續輸入解鎖碼
提示SIM卡永久被鎖
android網絡請求庫volley方法詳解,androidvolley使用volley進行網絡請求:需先將volley包導入androidstudio中 File下的P
安卓第五天筆記-對話框,安卓第五天筆記安卓第五天筆記--對話框 1.對話框 AlerDialog :功能最豐富 PorgressDialog:進度對話框 DatePick
01-安卓環境初搭建,01-安卓環境搭建需要的軟件如沒有提供下載鏈接,文章中會注明! 首先下載 eclipse 安裝!(筆者提供的鏈接中沒有Eclipse下載!) 安裝完
Android studio 百度地圖開發(1)配置工程、顯示地圖 Android studio 百度地圖開發(1)配置工程、顯示地圖 email:chentravell