中文字幕日韩精品一区二区免费_精品一区二区三区国产精品无卡在_国精品无码专区一区二区三区_国产αv三级中文在线

怎么在Android中識(shí)別預(yù)裝的第三方App-創(chuàng)新互聯(lián)

這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)?lái)有關(guān)怎么在Android中識(shí)別預(yù)裝的第三方App,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

創(chuàng)新互聯(lián)公司網(wǎng)站建設(shè)公司提供網(wǎng)站設(shè)計(jì)和自適應(yīng)建站服務(wù)。團(tuán)隊(duì)由有經(jīng)驗(yàn)的網(wǎng)頁(yè)設(shè)計(jì)師、程序員和市場(chǎng)專家組成,能夠提供從H5頁(yè)面制作,網(wǎng)站制作,廣告投放平臺(tái),模板建站到成都微信小程序等全方位服務(wù)。 以客戶為中心,致力于為客戶提供創(chuàng)新、高效的解決方案,幫助您打造成功的企業(yè)網(wǎng)站。
<package name="com.tencent.mm" 
codePath="/data/app/com.tencent.mm-TSn6yG4fF7A_EaxE5OtrHQ==" 
nativeLibraryPath="/data/app/com.tencent.mm-TSn6yG4fF7A_EaxE5OtrHQ==/lib" 
primaryCpuAbi="armeabi" publicFlags="945307204" 
privateFlags="0" ft="167702c7508" it="1676feab448" 
ut="167702c8a57" version="1360" userId="10118">
...
</package>

<package name="com.android.providers.downloads" 
codePath="/system/priv-app/DownloadProvider" 
nativeLibraryPath="/system/priv-app/DownloadProvider/lib" publicFlags="944258629" 
privateFlags="8" ft="11e8dc5d800" it="11e8dc5d800" 
ut="11e8dc5d800" version="28" sharedUserId="10006" isOrphaned="true">
...
</package>

其中it的值便是安裝時(shí)間,這里是用十六進(jìn)制保存的,上面這2個(gè)App的安裝時(shí)間換算成十進(jìn)制分別是1543770911816和1230739200000,對(duì)應(yīng)的北京時(shí)間即2018-12-03 01:15:11和2009-01-01 00:00:00。 【嗯…想不到我12月3號(hào)1點(diǎn)多還沒(méi)睡,還安裝了個(gè)微信……】

系統(tǒng)啟動(dòng)時(shí),PackageManagerService由SystemServer啟動(dòng),PackageManagerService會(huì)掃描/data/app、/system/app、/system/priv-app、/vendor/app等等目錄,可以理解為會(huì)把這些目錄中的Apk安裝一遍,PackageManagerService會(huì)結(jié)合上面提到的packages.xml把各個(gè)App解析成PackageParser.Package對(duì)象。

思路

根據(jù)上面的知識(shí),我們可以知道,如果packages.xml已經(jīng)有了某個(gè)App的信息,那么這個(gè)App的安裝時(shí)間肯定就是packages.xml中記錄的時(shí)間。第一次啟動(dòng)手機(jī)時(shí)packages.xml文件還不存在,或者新安裝一個(gè)App時(shí),packages.xml中還沒(méi)有這個(gè)App的記錄,也就是說(shuō),確認(rèn)這個(gè)packages.xml中的firstInstallTime(即it)是如果生成的便是問(wèn)題的關(guān)鍵。

以下基于7.0.0_r1版本代碼。

通過(guò)搜索PackageManagerService,在scanPackageDirtyLI方法中有這么一段代碼:

// Take care of first install / last update times.
if (currentTime != 0) {
 if (pkgSetting.firstInstallTime == 0) {
 pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = currentTime;
 } else if ((scanFlags&SCAN_UPDATE_TIME) != 0) {
 pkgSetting.lastUpdateTime = currentTime;
 }
} else if (pkgSetting.firstInstallTime == 0) {
 // We need *something*. Take time time stamp of the file.
 pkgSetting.firstInstallTime = pkgSetting.lastUpdateTime = scanFileTime;
} else if ((policyFlags&PackageParser.PARSE_IS_SYSTEM_DIR) != 0) {
 if (scanFileTime != pkgSetting.timeStamp) {
 // A package on the system image has changed; consider this
 // to be an update.
 pkgSetting.lastUpdateTime = scanFileTime;
 }
}

其中,currentTime是scanPackageDirtyLI方法的一個(gè)參數(shù)。pkgSetting是從packages.xml中讀取到的該App的信息(PackageSetting對(duì)象),如果packages.xml中不存在這個(gè)App的信息,會(huì)根據(jù)從Apk中解析到的信息創(chuàng)建一個(gè)PackageSetting。scanFileTime是Apk文件的最后修改時(shí)間。
可以看到存在這么幾種情況:

  • 傳入的currentTime不為0,從packages.xml中讀取到的firstInstallTime為0。這種情況會(huì)將firstInstallTime和lastUpdateTime均設(shè)置為傳入的currentTime的值。

  • 傳入的currentTime不為0,傳入的scanFlags設(shè)置了SCAN_UPDATE_TIME。這種情況會(huì)將lastUpdateTime設(shè)置為傳入的currentTime的值。

  • 傳入的currentTime為0,從packages.xml中讀取到的firstInstallTime為0。這種情況會(huì)將firstInstallTime和lastUpdateTime均設(shè)置為Apk的最后修改時(shí)間。

  • 傳入的currentTime為0,從packages.xml中讀取到的firstInstallTime不為0,傳入的policyFlags設(shè)置了PackageParser.PARSE_IS_SYSTEM_DIR,scanFileTime與packages.xml中讀取到的timeStamp(packages.xml中package標(biāo)簽的ft)不相同。這種情況會(huì)將lastUpdateTime設(shè)置為Apk的最后修改時(shí)間。

對(duì)應(yīng)到我們真實(shí)使用手機(jī)的場(chǎng)景,上面4種情況分別對(duì)應(yīng)以下幾種場(chǎng)景:

  • 第一種情況:對(duì)應(yīng)新安裝App。currentTime為當(dāng)前的時(shí)間戳,會(huì)將這個(gè)新安裝的App的firstInstallTime和lastUpdateTime設(shè)置為當(dāng)前時(shí)間戳。

  • 第二種情況:對(duì)應(yīng)更新App。currentTime為當(dāng)前的時(shí)間戳,會(huì)將lastUpdateTime設(shè)置為當(dāng)前時(shí)間戳,firstInstallTime保持不變。

  • 第三種情況:手機(jī)啟動(dòng)時(shí)PackageManagerService掃描各個(gè)目錄時(shí)發(fā)現(xiàn)了packages.xml中不存在的App(第一次啟動(dòng)時(shí)所有App都不在packages.xml中)。

  • 第四種情況:系統(tǒng)更新等操作更新了系統(tǒng)分區(qū)的App,導(dǎo)致其文件的最后修改時(shí)間和記錄的不一致了,會(huì)被認(rèn)為是更新。

我們可以大膽猜測(cè),第一次啟動(dòng)手機(jī)時(shí)會(huì)走第三種情況,因此系統(tǒng)App和預(yù)裝App的安裝時(shí)間是文件的最后修改時(shí)間,而這些文件的最后修改時(shí)間都是整秒的。

如何驗(yàn)證?

我們先看看上面那個(gè)com.android.providers.downloads的Apk文件的最后修改時(shí)間。

# stat DownloadProvider.apk
 File: `DownloadProvider.apk'
 Size: 504712	 Blocks: 992	 IO Blocks: 512	regular file
Device: 10305h/66309d	 Inode: 1308	 Links: 1
Access: (644/-rw-r--r--)	Uid: ( 0/ root)	Gid: ( 0/ root)
Access: 2009-01-01 00:00:00.000000000
Modify: 2009-01-01 00:00:00.000000000
Change: 2009-01-01 00:00:00.000000000

時(shí)間與packages.xml中保存的時(shí)間一致,確實(shí)是把文件的最后修改時(shí)間作為了安裝時(shí)間。那么還有一個(gè)問(wèn)題需要確認(rèn),傳入的currentTime是0嗎?

我們追溯調(diào)用鏈,會(huì)在PackageManagerService的構(gòu)造函數(shù)中看到掃描各個(gè)目錄的方法。調(diào)用scanDirTracedLI方法傳入的最后一個(gè)參數(shù)0即scanPackageDirtyLI方法中的currentTime。感興趣的還可以仔細(xì)看看PackageManagerService到底掃描了哪些目錄。

File vendorOverlayDir = new File(VENDOR_OVERLAY_DIR);
scanDirTracedLI(vendorOverlayDir, mDefParseFlags
  | PackageParser.PARSE_IS_SYSTEM
  | PackageParser.PARSE_IS_SYSTEM_DIR
  | PackageParser.PARSE_TRUSTED_OVERLAY, scanFlags | SCAN_TRUSTED_OVERLAY, 0);

// Find base frameworks (resource packages without code).
scanDirTracedLI(frameworkDir, mDefParseFlags
  | PackageParser.PARSE_IS_SYSTEM
  | PackageParser.PARSE_IS_SYSTEM_DIR
  | PackageParser.PARSE_IS_PRIVILEGED,
  scanFlags | SCAN_NO_DEX, 0);

// Collected privileged system packages.
final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
scanDirTracedLI(privilegedAppDir, mDefParseFlags
  | PackageParser.PARSE_IS_SYSTEM
  | PackageParser.PARSE_IS_SYSTEM_DIR
  | PackageParser.PARSE_IS_PRIVILEGED, scanFlags, 0);

// Collect ordinary system packages.
final File systemAppDir = new File(Environment.getRootDirectory(), "app");
scanDirTracedLI(systemAppDir, mDefParseFlags
  | PackageParser.PARSE_IS_SYSTEM
  | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);

// Collect all vendor packages.
File vendorAppDir = new File("/vendor/app");
try {
 vendorAppDir = vendorAppDir.getCanonicalFile();
} catch (IOException e) {
 // failed to look up canonical path, continue with original one
}
scanDirTracedLI(vendorAppDir, mDefParseFlags
  | PackageParser.PARSE_IS_SYSTEM
  | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);

// Collect all OEM packages.
final File oemAppDir = new File(Environment.getOemDirectory(), "app");
scanDirTracedLI(oemAppDir, mDefParseFlags
  | PackageParser.PARSE_IS_SYSTEM
  | PackageParser.PARSE_IS_SYSTEM_DIR, scanFlags, 0);

...

scanDirTracedLI(mAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);

scanDirTracedLI(mDrmAppPrivateInstallDir, mDefParseFlags
  | PackageParser.PARSE_FORWARD_LOCK,
  scanFlags | SCAN_REQUIRE_KNOWN, 0);

如果感興趣,你可以去跟一下安裝App和更新App的代碼,看傳入的currentTime是不是當(dāng)前的時(shí)間戳。

到此,我們已經(jīng)證明了第一次啟動(dòng)手機(jī)時(shí),系統(tǒng)會(huì)把文件的最后修改時(shí)間當(dāng)成系統(tǒng)App和預(yù)裝App的安裝時(shí)間,而這個(gè)時(shí)間一般是類似于上面那樣2009-01-01 00:00:00.000000000的整秒的時(shí)間(至于為什么是這樣,那就是另一個(gè)問(wèn)題了),而我們自己安裝App時(shí)幾乎不可能在一個(gè)整秒的時(shí)間安裝,所有我們可以用安裝時(shí)間是否為整秒來(lái)區(qū)分手機(jī)預(yù)裝的App和用戶手動(dòng)安裝的App

上述就是小編為大家分享的怎么在Android中識(shí)別預(yù)裝的第三方App了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。

文章名稱:怎么在Android中識(shí)別預(yù)裝的第三方App-創(chuàng)新互聯(lián)
轉(zhuǎn)載源于:http://www.rwnh.cn/article24/epgje.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供建站公司、企業(yè)建站商城網(wǎng)站、手機(jī)網(wǎng)站建設(shè)定制網(wǎng)站、企業(yè)網(wǎng)站制作

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

商城網(wǎng)站建設(shè)
城步| 宜川县| 多伦县| 芜湖县| 抚宁县| 安徽省| 资溪县| 梁山县| 鄂托克旗| 湘西| 施秉县| 宕昌县| 康保县| 满洲里市| 独山县| 江永县| 河西区| 加查县| 金塔县| 方城县| 四川省| 博湖县| 稷山县| 陇南市| 徐水县| 灵丘县| 聂荣县| 铁力市| 东阳市| 武川县| 双城市| 迁西县| 辰溪县| 延寿县| 屯门区| 永昌县| 张北县| 敦化市| 苏尼特左旗| 白水县| 开封市|