實(shí)現(xiàn)一個(gè)Android鎖屏App功能的難點(diǎn)總結(jié)
自定義一個(gè)漂亮實(shí)用的鎖屏app,如果能贏得用戶的認(rèn)可,替換系統(tǒng)自帶的鎖屏,絕對(duì)是一個(gè)不小的日活入口。這段時(shí)間正好總結(jié)一下最近調(diào)研的Android平臺(tái)的鎖屏app開(kāi)發(fā)中的難點(diǎn)。
一、前言
鎖屏的大概實(shí)現(xiàn)原理都很簡(jiǎn)單。監(jiān)聽(tīng)系統(tǒng)的亮屏廣播,在亮屏的時(shí)候展示自己的鎖屏界面,用戶在鎖屏界面上進(jìn)行一系列的動(dòng)作才能解鎖。有的手機(jī)啟動(dòng)鎖屏界面的過(guò)程會(huì)很卡,所以會(huì)明顯看到亮屏之后鎖屏界面的啟動(dòng)有延時(shí),因此也可以選擇監(jiān)聽(tīng)系統(tǒng)滅屏的廣播,屏幕關(guān)掉的時(shí)候就將鎖屏界面準(zhǔn)備好,直接亮屏展示(滅屏后你的app會(huì)比較容易被殺死,這點(diǎn)要注意做?;睿?。
還需要注意,亮屏和滅屏廣播,SCREEN_ON/SCREEN_OFF都是只能動(dòng)態(tài)監(jiān)聽(tīng)的,所以要另開(kāi)一個(gè)Service來(lái)注冊(cè),這個(gè)Service的自啟動(dòng)和?;钜惨龊谩?/p>
基本的實(shí)現(xiàn)細(xì)節(jié)就不多講了,這篇文章只會(huì)講遇到的幾個(gè)難點(diǎn)。
二、鎖屏實(shí)現(xiàn)中的難點(diǎn)
1.屏蔽Home鍵
既然是鎖屏界面,當(dāng)然只能通過(guò)界面上的一些滑動(dòng)或者輸入動(dòng)作來(lái)解開(kāi)鎖屏,不能簡(jiǎn)單的直接被Home鍵一按,就解開(kāi)了。從4.0開(kāi)始,Home直接在framework層就被系統(tǒng)響應(yīng)到,強(qiáng)退到桌面,第三方應(yīng)用里已經(jīng)無(wú)法再通過(guò)Activity.onKeyDown方法來(lái)監(jiān)聽(tīng)和攔截Home鍵,盡管還象征性的保留了Home鍵的KeyCode來(lái)向前兼容,但是Home鍵按下去,并不會(huì)回調(diào)這個(gè)方法。
除了onKeyDown,有沒(méi)有其他辦法監(jiān)聽(tīng)Home鍵,有的。前臺(tái)App退到后臺(tái)會(huì)有廣播ACTION_CLOSE_SYSTEM_DIALOGS,收到廣播攜帶的intent之后,解析里面的"reason"參數(shù),就可以知道退出原因是什么了。home鍵按下后,reason是"homekey",最近任務(wù)鍵按下后,reason是"recentapps"。
這當(dāng)然不是最終方案,因?yàn)橛行┤荝OM里并不會(huì)有這個(gè)廣播。而且廣播的意思只是通知你一下,人家framework層已經(jīng)把你的應(yīng)用退回桌面了,你能監(jiān)聽(tīng)home鍵,但沒(méi)有辦法攔截home鍵。也許想到了可以監(jiān)聽(tīng)到home鍵的時(shí)候,馬上把自己的Activity又重新打開(kāi)展示,我試了一下,home鍵按下后startActivity會(huì)有延時(shí)3秒左右,這應(yīng)該是Google早就想到了我們會(huì)這么干,做了這么一個(gè)延時(shí)方案。
直接攔截行不通了,想想別的路子。按Home鍵是讓系統(tǒng)退回到Launcher(即桌面啟動(dòng)器),那么如果我們的鎖屏Activity本身就是Launcher的話,那按Home鍵不就等于回到我們的鎖屏Activity,也就可以阻止它把鎖屏Activity關(guān)掉了。
怎么把自己的Activity聲明為L(zhǎng)auncher,在Activity中添加intent-filter:
<intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.HOME" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter>
這樣,新安裝的app會(huì)是一個(gè)能夠作為launcher的app,所以首次按Home鍵的時(shí)候,就會(huì)有彈窗提示你選擇要進(jìn)入哪個(gè)launcher,選擇我們自己的Activity,這樣home鍵就被我們接管了。
不過(guò)這樣有一個(gè)很明顯的問(wèn)題,如果不在我們的鎖屏界面按Home鍵,同樣會(huì)進(jìn)入到鎖屏Activity。當(dāng)然,解決的方式也簡(jiǎn)單,當(dāng)我們按Home時(shí)進(jìn)入鎖屏Activity的onCreate里做一個(gè)判斷,如果前一個(gè)前臺(tái)Activity是鎖屏Activity,那就不用對(duì)Home鍵處理,如果不是鎖屏Activity,那就要關(guān)閉鎖屏Activity,跳到用戶真正的桌面啟動(dòng)器去了。真正的桌面啟動(dòng)器是哪一個(gè),我們可以這樣來(lái)找:
List<String> pkgNamesT = new ArrayList<String>(); List<String> actNamesT = new ArrayList<String>(); List<ResolveInfo> resolveInfos = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); for (int i = 0; i < resolveInfos.size(); i++) { String string = resolveInfos.get(i).activityInfo.packageName; if (!string.equals(context.getPackageName())) {//自己的launcher不要 pkgNamesT.add(string); string = resolveInfos.get(i).activityInfo.name; actNamesT.add(string); } }
如果實(shí)際的launcher只有一個(gè),那直接跳轉(zhuǎn)過(guò)去就可以了:
ComponentName componentName = new ComponentName(pkgName, actName); Intent intent = new Intent(); intent.setComponent(componentName); context.startActivity(intent); ((Activity) context).finish();
如果手機(jī)安裝有多個(gè)launcher(如360桌面一類的app)就會(huì)麻煩一點(diǎn),需要展示一個(gè)列表讓用戶來(lái)選取用哪個(gè)launcher,這個(gè)在產(chǎn)品形態(tài)上可能會(huì)讓用戶覺(jué)得有點(diǎn)不解。
現(xiàn)在,如果在其他APP里按一下Home鍵,會(huì)跳到我們的鎖屏Activity然后跳轉(zhuǎn)到真正的launcher。這里可能會(huì)有Activity閃現(xiàn)一下的場(chǎng)景,影響用戶體驗(yàn)。最優(yōu)的辦法其實(shí)是另外弄一個(gè)Activity來(lái)作為Home鍵跳轉(zhuǎn)的Activity,這個(gè)Activity設(shè)為透明的,就不會(huì)被用戶感知。如此,產(chǎn)品形態(tài)就變成了,鎖屏Activity中按Home鍵,跳轉(zhuǎn)到透明Activity,跳轉(zhuǎn)回鎖屏Activity,相當(dāng)于Home鍵無(wú)效;其他APP中按Home鍵,跳轉(zhuǎn)到透明Activity,跳轉(zhuǎn)到真正的桌面。
實(shí)現(xiàn)透明的Activity,只需要在xml中聲明
android:theme="@android:style/Theme.Translucent.NoTitleBar"
這樣的界面是透明的,實(shí)際上有占位在屏幕的頂層,所以跳轉(zhuǎn)后記得要finish掉,不然會(huì)阻斷跳轉(zhuǎn)后的界面的交互。另外,Theme.NoDisplay也能將Activity設(shè)置為不可見(jiàn),而且不占位,但是筆者實(shí)現(xiàn)的時(shí)候發(fā)現(xiàn),NoDisplay的Activity無(wú)法被系統(tǒng)設(shè)置為launcher(設(shè)置后會(huì)彈窗讓你重新設(shè)置,如此反復(fù))
2.懸浮窗的實(shí)現(xiàn)方式
由于受Home鍵無(wú)法直接攔截的限制,Activity實(shí)現(xiàn)的鎖屏?xí)枰@較多的路。所以有的鎖屏應(yīng)用會(huì)使用懸浮窗來(lái)實(shí)現(xiàn),懸浮窗能夠無(wú)視Home鍵,在按下home鍵的時(shí)候不會(huì)退到后臺(tái)。所以不需要在home鍵的問(wèn)題上糾結(jié)。懸浮窗統(tǒng)一由WindowManager來(lái)管理,具體的實(shí)現(xiàn)比較簡(jiǎn)單,筆者就不贅述了,有個(gè)坑要注意,懸浮窗需要聲明權(quán)限:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
有的手機(jī)設(shè)置里,默認(rèn)是不給應(yīng)用授權(quán)懸浮窗使用權(quán)的,所以應(yīng)用里還要考慮引導(dǎo)用戶授權(quán)懸浮窗使用。
此外,有些應(yīng)急解鎖的場(chǎng)景,比如來(lái)電接聽(tīng),鬧鈴處理,對(duì)于Activity實(shí)現(xiàn)的鎖屏界面,系統(tǒng)會(huì)自動(dòng)把所有的前臺(tái)Activity隱藏,讓用戶直接去處理這些場(chǎng)景。但是懸浮窗會(huì)蓋住場(chǎng)景,所以遇到這些場(chǎng)景,懸浮窗實(shí)現(xiàn)的鎖屏界面要自己去處理這些特殊場(chǎng)景的自動(dòng)解鎖。
3.禁用系統(tǒng)鎖屏
有了自己的鎖屏界面,還需要禁用掉系統(tǒng)的鎖屏,以免造成用戶需要解鎖兩次的局面。
首先我們需要知道用戶是否設(shè)置了鎖屏,方法如下:
對(duì)于API Level 16及以上SDK,可以使用如下方法判斷是否有鎖:
((KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE)).isKeyguardSecure()
對(duì)API Level 15及以下SDK,可以使用反射來(lái)判斷:
try { Class<?> clazz = Class.forName("com.android.internal.widget.LockPatternUtils"); Constructor<?> constructor = clazz.getConstructor(Context.class); constructor.setAccessible(true); Object utils = constructor.newInstance(this); Method method = clazz.getMethod("isSecure"); return (Boolean) method.invoke(utils); }catch (Exception e){ e.printStackTrace(); }
好了,得知用戶設(shè)置了系統(tǒng)鎖屏,怎么關(guān)掉呢?有前人建議了這種方法
KeyguardManager km = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE); KeyguardManager.KeyguardLock keyguardLock = km.newKeyguardLock(""); keyguardLock.disableKeyguard();
需要權(quán)限
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
但經(jīng)筆者測(cè)驗(yàn),這種方法只能禁用滑動(dòng)鎖,如果用戶設(shè)置的是圖案或者PIN的鎖的話,是無(wú)法直接取消的。禁用掉密碼鎖或者圖案鎖是一個(gè)很危險(xiǎn)的行為,基于此,Google應(yīng)該是不會(huì)把它開(kāi)放給開(kāi)發(fā)者的,所以現(xiàn)在的鎖屏應(yīng)用的禁用鎖的辦法,都是直接跳到系統(tǒng)鎖屏設(shè)置界面,直接引導(dǎo)用戶去手動(dòng)關(guān)閉。可以通過(guò)如下代碼跳到用戶鎖屏設(shè)置界面:
Intent in = new Intent(Settings.ACTION_SECURITY_SETTINGS); startActivity(in);
這個(gè)也會(huì)有些許的兼容性問(wèn)題,比如,360手機(jī)的ROM并沒(méi)有把設(shè)置系統(tǒng)鎖屏的功能放在安全設(shè)置中,所以打開(kāi)安全設(shè)置的界面找不到取消系統(tǒng)鎖屏的地方,這個(gè)在一眾鎖屏應(yīng)用中并沒(méi)有做兼容。
三、附加功能中的難點(diǎn)
上面的功能都是直接針對(duì)鎖屏本身的實(shí)現(xiàn)來(lái)說(shuō)的。鎖屏應(yīng)用除了本身能夠有“鎖住屏幕”的功能外,還應(yīng)該有其他一些漂亮又實(shí)用的功能,最起碼應(yīng)該是盡量往系統(tǒng)鎖屏的樣式上靠攏并發(fā)揮,才方便被用戶接受。
1.獲取通知
新的Notification到來(lái)時(shí)應(yīng)該展示在鎖屏界面上,所以我們需要對(duì)通知欄進(jìn)行監(jiān)聽(tīng)。從Android 4.3(api 18)開(kāi)始,Google給我們提供了一個(gè)NotificationListenerService類,第三方應(yīng)用可以更方便的獲得通知欄使用權(quán)(Notification Access),當(dāng)然,這么敏感的權(quán)限得要應(yīng)用自己聲明,同時(shí)還要引導(dǎo)用戶手動(dòng)授權(quán)。如下,建立一個(gè)NotificationMonitor類繼承于NotificationListenerService,并聲明權(quán)限:
<service android:name=".NotificationMonitor" android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"> <intent-filter> <action android:name="android.service.notification.NotificationListenerService" /> </intent-filter> </service>
然后同引導(dǎo)用戶關(guān)閉系統(tǒng)鎖屏一樣,要引導(dǎo)用戶來(lái)授權(quán)通知欄使用權(quán):
startActivity(new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS));
可以通過(guò)如下代碼檢查到通知欄使用權(quán)是否已經(jīng)拿到:
private boolean isNotificationListenEnabled(){ String pkgName = getPackageName(); final String flat = Settings.Secure.getString(getContentResolver(), "enabled_notification_listeners"); if (!TextUtils.isEmpty(flat)) { final String[] names = flat.split(":"); for (int i = 0; i < names.length; i++) { final ComponentName cn = ComponentName.unflattenFromString(names[i]); if (cn != null) { if (TextUtils.equals(pkgName, cn.getPackageName())) { return true; } } } } return false; }
拿到通知欄使用權(quán)后,系統(tǒng)通知欄的變化就可以在NotificationMonitor里面監(jiān)聽(tīng)到了:
public class NotificationMonitor extends NotificationListenerService { @Override public IBinder onBind(Intent intent) { // TODO: Return the communication channel to the service. return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { return super.onStartCommand(intent,flags,startId); } //新的Notification到達(dá) @Override public void onNotificationPosted(StatusBarNotification sbn) { super.onNotificationPosted(sbn); } //新的Notification到達(dá),api 21新增 @Override public void onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap) { super.onNotificationPosted(sbn, rankingMap); } //Notification被移除 @Override public void onNotificationRemoved(StatusBarNotification sbn) { super.onNotificationRemoved(sbn); } //Notification被移除,api 21新增 @Override public void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap) { super.onNotificationRemoved(sbn, rankingMap); } //Notification排序變動(dòng),api 21新增 @Override public void onNotificationRankingUpdate(RankingMap rankingMap) { super.onNotificationRankingUpdate(rankingMap); } //Service與系統(tǒng)通知欄完成綁定時(shí)回調(diào),綁定后才能收到通知欄回調(diào),api 21新增 @Override public void onListenerConnected() { super.onListenerConnected(); } }
同時(shí),NotificationListenerService還提供了cancelNotification和cancelAllNotification方法,用于移除通知欄的通知,可以很方便的實(shí)現(xiàn)在自定義的鎖屏界面移除掉通知了。
筆者實(shí)現(xiàn)這個(gè)類的時(shí)候發(fā)現(xiàn)了一個(gè)坑,所有的代碼都是OK的,通知欄使用權(quán)也授權(quán)了,但是來(lái)通知時(shí)始終沒(méi)有回調(diào)onNotificationPosted,查問(wèn)題查了很久,后來(lái)看到網(wǎng)上有人遇到同樣的問(wèn)題,另外新建了一個(gè)類把代碼復(fù)制過(guò)去,就OK了,這樣看來(lái)應(yīng)該是編譯器的問(wèn)題。
獲取了通知欄使用權(quán)的Service天然就能被?;?,如果被殺死,Android系統(tǒng)能夠?qū)⑺貑?。所以平時(shí)看到一些應(yīng)用要求獲取通知欄使用權(quán)時(shí),要注意這類應(yīng)用會(huì)永久駐存后臺(tái)的。當(dāng)然,如果這個(gè)Service所在進(jìn)程崩潰達(dá)到一定次數(shù)的話,Android系統(tǒng)也會(huì)灰心,在下次關(guān)機(jī)重啟前不會(huì)再將Service重啟,所以,開(kāi)發(fā)中最好能將這個(gè)Service放在一個(gè)輕量獨(dú)立的進(jìn)程中。
2.獲取HotSeat區(qū)快捷方式
桌面快捷方式分為兩類,Desktop區(qū),指隨著屏幕滾動(dòng)的那部分,HotSeat區(qū),指放置于桌面底部不隨屏幕滾動(dòng)的部分。用戶自定義的HotSeat區(qū)里的快捷方式屬于常用的應(yīng)用。如果能夠在鎖屏界面也添加這部分的快捷啟動(dòng),會(huì)是一個(gè)比較友好的功能。這個(gè)的主要問(wèn)題是,怎么獲取到HotSeat區(qū)的快捷方式呢。
系統(tǒng)快捷方式存儲(chǔ)在數(shù)據(jù)庫(kù)文件launcher.db中的favorites表中,如圖所示:
可以看到有對(duì)應(yīng)的快捷方式的id,title和intent,這個(gè)container屬性是用來(lái)指示所在文件夾的id,然而可以看到有的container為負(fù)數(shù)。這是為什么,筆者查看了一下Android Launcher相關(guān)的源碼,找到這么兩句:
/** * The icon is a resource identified by a package name and an integer id. */ public static final int CONTAINER_DESKTOP = -100; public static final int CONTAINER_HOTSEAT = -101;
也就是說(shuō),container為-100的是Desktop區(qū)的快捷方式,container為-101的正是要找的HotSeat區(qū)的快捷方式。
現(xiàn)在知道了快捷方式的存儲(chǔ)方式,接下來(lái)的問(wèn)題就是去找launcher.db文件的路徑。
在不同版本的Android原生api中,由于默認(rèn)使用的launcher啟動(dòng)器的包名不一樣,launcher.db存儲(chǔ)的路徑也不一樣。
Android API 7及以下:/data/data/com.android.launcher/databases/laucher.db
Android API 8~18:/data/data/com.android.launcher2/databases/laucher.db
Android API 19及以上:/data/data/com.android.launcher3/databases/laucher.db
而對(duì)于各式各樣的第三方ROM,使用了千奇百怪的laucher包名,這個(gè)路徑就更亂了:
HTC: /data/data/com.htc.launcher/databases/laucher.db
360: /data/data/net.qihoo360.launcher/databases/laucher.db
華為: /data/data/com.huawei.launcher3/databases/laucher.db
小米: /data/data/com.miui.mihome2/databases/laucher.db
...
當(dāng)然,我們不會(huì)通過(guò)直接讀取數(shù)據(jù)庫(kù)的方式來(lái)獲取快捷方式的信息,系統(tǒng)自帶的laucher會(huì)提供ContentProvider給外部讀取。避開(kāi)了對(duì)數(shù)據(jù)庫(kù)路徑做兼容的大坑,轉(zhuǎn)眼就掉進(jìn)了另一個(gè)大坑,通過(guò)Provider來(lái)讀取快捷方式,所需要的權(quán)限和URI也需要做兼容。
從快捷方式的存儲(chǔ)可見(jiàn),Android 的碎片化是多么的嚴(yán)重,所以最后筆者決定不再深入去兼容實(shí)現(xiàn),這是得不償失的行為,有興趣實(shí)現(xiàn)的可以看看這篇文章,判斷一個(gè)快捷方式是否存在是多么的難:http://www.jianshu.com/p/dc3d...
3.獲取壁紙
鎖屏界面的背景和手機(jī)桌面壁紙保持一致,不至于讓用戶覺(jué)得突兀,這里有兩種辦法實(shí)現(xiàn)獲取壁紙。
Activity Style模式
如果是Activity實(shí)現(xiàn)的鎖屏界面,可以直接設(shè)置Activity的theme就可以用壁紙做背景了。
android:theme="@android:style/Theme.Wallpaper.NoTitleBar"
WallPaperManager模式
懸浮窗模式的鎖屏界面無(wú)法用theme,那么可以通過(guò)WallPaperManager來(lái)獲取壁紙。
// 獲取壁紙管理器 WallpaperManager wallpaperManager = WallpaperManager .getInstance(this); // 獲取當(dāng)前壁紙 Drawable wallpaperDrawable = wallpaperManager.getDrawable(); // 將Drawable,轉(zhuǎn)成Bitmap Bitmap bm = ((BitmapDrawable) wallpaperDrawable).getBitmap(); mRootView.setBackgroundDrawable(new BitmapDrawable(bm));
這種方式在小米等仿iOS的一屏桌面上是OK的,但是在原生Android那樣的兩屏桌面(快捷方式與全部app分別在不同屏),快捷方式那屏獲取的壁紙是一整張大壁紙,而實(shí)際laucher顯示的是切割后的壁紙。所以以上方式會(huì)把尺寸不符的壁紙?jiān)O(shè)為了背景。需要自己去根據(jù)laucher的屏數(shù)和當(dāng)前是第幾屏來(lái)進(jìn)行切圖,laucher的總屏數(shù)可以在上述launcher.db里的workspaceScreens表里找到,而具體當(dāng)前在第幾屏是存在launcher app內(nèi)存實(shí)例中的,無(wú)法獲取。如果真要切的話,建議直接按照屏幕寬高切下整張壁紙的左邊一屏就好了。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Java實(shí)現(xiàn)兩人五子棋游戲(七) 屏幕提示信息
- Java實(shí)現(xiàn)的簡(jiǎn)單網(wǎng)頁(yè)截屏功能示例
- 微信小程序?qū)崿F(xiàn)手勢(shì)圖案鎖屏功能
- swift4.0實(shí)現(xiàn)視頻播放、屏幕旋轉(zhuǎn)、倍速播放、手勢(shì)調(diào)節(jié)及鎖屏面板等功能實(shí)例
- iOS監(jiān)聽(tīng)手機(jī)鎖屏狀態(tài)
- Android如何實(shí)現(xiàn)鎖屏狀態(tài)下彈窗
- 設(shè)置Android系統(tǒng)永不鎖屏永不休眠的方法
- Java防鎖屏小程序代碼實(shí)例
相關(guān)文章
Android自定義View之酷炫數(shù)字圓環(huán)
這篇文章主要為大家詳細(xì)介紹了Android自定義View之酷炫數(shù)字圓環(huán),實(shí)現(xiàn)效果很酷,,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-01-01Android利用BitMap獲得圖片像素?cái)?shù)據(jù)的方法
這篇文章主要介紹了Android利用BitMap獲得圖片像素?cái)?shù)據(jù)的方法,結(jié)合實(shí)例對(duì)比分析了Android獲取圖片像素?cái)?shù)據(jù)的相關(guān)技巧,需要的朋友可以參考下2016-02-02FFmpeg?Principle學(xué)習(xí)new_video_stream添加視頻輸出流
這篇文章主要為大家介紹了FFmpeg?Principle學(xué)習(xí)new_video_stream添加視頻輸出流示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10android判斷一個(gè)Activity是否處于棧頂?shù)膶?shí)例
下面小編就為大家分享一篇android判斷一個(gè)Activity是否處于棧頂?shù)膶?shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-03-03Android編程實(shí)現(xiàn)將壓縮數(shù)據(jù)庫(kù)文件拷貝到安裝目錄的方法
這篇文章主要介紹了Android編程實(shí)現(xiàn)將壓縮數(shù)據(jù)庫(kù)文件拷貝到安裝目錄的方法,涉及Android處理壓縮文件的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-10-10詳解Android更改APP語(yǔ)言模式的實(shí)現(xiàn)過(guò)程
本文詳細(xì)介紹如何更改Android中APP的語(yǔ)言模式,這個(gè)功能對(duì)于大家開(kāi)發(fā)Android APP很有幫助,本文運(yùn)用文字介紹和代碼示例把過(guò)程寫(xiě)的很詳細(xì),有需要的可以參考借鑒。2016-08-08Android實(shí)現(xiàn)文件存儲(chǔ)并讀取的示例代碼
本篇文章主要介紹了Android實(shí)現(xiàn)文件存儲(chǔ)的示例代碼,文件內(nèi)容可以分別存儲(chǔ)在手機(jī)內(nèi)存和外存中,并且都可以讀去取出來(lái),有興趣的可以了解一下。2017-01-01Android手機(jī)衛(wèi)士之設(shè)置密碼對(duì)話框
這篇文章主要為大家詳細(xì)介紹了Android手機(jī)衛(wèi)士之設(shè)置密碼對(duì)話框,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-10-10