仿iOS獵豹垃圾清理

轉(zhuǎn)載請(qǐng)注明出處:
仿獵豹垃圾清理(實(shí)現(xiàn)原理+源碼)
前幾天無(wú)意打開(kāi)獵豹內(nèi)存大師, 發(fā)現(xiàn)它的垃圾清理很強(qiáng)大, 效果也不錯(cuò),
閑著就研究了下乏奥。 不過(guò).. 結(jié)果貌似和我想象的不太一樣。怎么說(shuō)呢,
聽(tīng)我下文一一分析判呕。

效果圖:



從效果圖, 我們可以看出它有以下幾個(gè)功能:
獲取設(shè)備上已安裝的所有App
獲取App的信息, 包括圖標(biāo)和名稱
獲取當(dāng)前已用存儲(chǔ)和可用存儲(chǔ)
掃描App動(dòng)畫(huà)效果
清除所有App垃圾文件

看到這里, 你是不是也覺(jué)得很強(qiáng)大?
然后然后, 感嘆的同時(shí), 我有幾點(diǎn)疑惑猾蒂。
獲取到所有已安裝的App, 這個(gè)功能能通過(guò)審核?(我是去年在App Store上下載的這個(gè)App)
App的圖標(biāo)如何獲取到的? (因?yàn)閽呙璧降腁pp包括我自己沒(méi)上架的demo, icon只能是本地獲取, 從其他App沙盒拿幌羞?)
垃圾清理過(guò)程, 為什么會(huì)出現(xiàn)“存儲(chǔ)容量已滿”這個(gè)提示? 明明是清理垃圾, 中途還會(huì)出現(xiàn)存儲(chǔ)滿的情況?

困惑, 不解..~ 于是乎, 折騰唄晚顷。 花了兩天時(shí)間峰伙。寫(xiě)了個(gè)小demo。
效果如下:



接下去, 我會(huì)介紹以下各個(gè)功能的實(shí)現(xiàn)過(guò)程, 包括:
獲取設(shè)備已安裝App列表已經(jīng)App信息
掃描動(dòng)畫(huà)的實(shí)現(xiàn)
獲取已用存儲(chǔ)和可用存儲(chǔ)
垃圾清理

不過(guò), 分析之前, 說(shuō)明一下,
該功能不能夠上傳到App Store上! 也就是說(shuō), 它通不過(guò)審核的
该默。
原因有二:\

  1. 使用了私有API\
  2. 蘋(píng)果不允許App有處理內(nèi)存相關(guān)功能

至于獵豹內(nèi)存大師這個(gè)App瞳氓、它也早已經(jīng) 被下架
了。我懷疑它利用混淆代碼通過(guò)的審核栓袖。至于功能的實(shí)現(xiàn),
我覺(jué)得和獵豹的實(shí)現(xiàn)思路應(yīng)該是一樣的匣摘。

至此, 如果你還對(duì)這篇文章感興趣, 歡迎繼續(xù)往下閱讀。
本文參考源碼:
CSDN下載_防獵豹垃圾清理
獲取設(shè)備已安裝App列表已經(jīng)App信息
不越獄, 非私有API
沒(méi)有越獄的設(shè)備裹刮,官方?jīng)]有提供api音榜,所以只能用一些技巧,但是獲取內(nèi)容不全捧弃。
這里主要有兩種辦法:
方法一:利用URL scheme赠叼,看對(duì)于某一應(yīng)用特有的urlscheme,有沒(méi)有響應(yīng)违霞。如果有響應(yīng)嘴办,就說(shuō)明安裝了這個(gè)特定的app。

說(shuō)實(shí)在.. 這個(gè)辦法比較傻买鸽。 App Store幾百萬(wàn)的App, 如何枚舉的過(guò)來(lái)? 并且,
也無(wú)法掃描到自己的demo涧郊。 不過(guò), 還真有人這么干..
這是對(duì)應(yīng)的demo, 感興趣可以看看。
iHasApp

官方教程:
iPhoneURLScheme_Reference

方法二:利用一些方法獲得當(dāng)前正在運(yùn)行的進(jìn)程信息眼五,從進(jìn)程信息中獲得安裝的app信息妆艘。


參考:
UIDevice_Category_For_Processes

總的來(lái)說(shuō), 不越獄, 非私有API, 想獲得完整列表, 基本沒(méi)什么可能。
不越獄, 私有API看幼。
這里就是我demo所采用的辦法, 比較簡(jiǎn)單批旺。

include <objc/runtime.h>Class LSApplicationWorkspace_class = objc_getClass("LSApplicationWorkspace"); NSObject* workspace = [LSApplicationWorkspace_class performSelector:@selector(defaultWorkspace)]; NSLog(@"apps: %@", [workspace performSelector:@selector(allApplications)]);

返回結(jié)果
"LSApplicationProxy: com.qunar.iphoneclient8", "LSApplicationProxy: com.apple.mobilemail", "LSApplicationProxy: com.apple.mobilenotes", "LSApplicationProxy: com.apple.compass", "LSApplicationProxy: com.tencent.happymj", "LSApplicationProxy: com.apple.mobilesafari", "LSApplicationProxy: com.apple.reminders"

返回的是個(gè)數(shù)據(jù), 每個(gè)元素都是 LSApplicationProxy
.它的description只返回了
它的bundle id。然而這并不是我們想要的诵姜。

接下去我們看
LSApplicationProxy.h
形如:
@class LSApplicationProxy, NSArray, NSDictionary, NSProgress, NSString, NSURL, NSUUID;@interface LSApplicationProxy : LSResourceProxy <NSSecureCoding> { NSArray *_UIBackgroundModes; NSString *_applicationType; NSArray *_audioComponents; unsigned int _bundleFlags; NSURL *_bundleURL; NSString *_bundleVersion; NSArray *_directionsModes; NSDictionary *_entitlements; NSDictionary *_envi ... ...

這里列舉了 LSApplicationProxy
對(duì)應(yīng)的屬性和方法朱沃。
我們可以用如下代碼, 打印下每個(gè)屬性的值, 找出我們想要的。
2、/* 獲取對(duì)象的所有屬性 以及屬性值 */- (NSDictionary *)properties_aps{ NSMutableDictionary *props = [NSMutableDictionary dictionary]; unsigned int outCount, i; objc_property_t properties = class_copyPropertyList([self class], &outCount); for (i = 0; i<outCount; i++) { objc_property_t property = properties[i]; const char char_f =property_getName(property); NSString *propertyName = [NSString stringWithUTF8String:char_f]; id propertyValue = [self valueForKey:(NSString *)propertyName]; if (propertyValue) [props setObject:propertyValue forKey:propertyName]; } free(properties); return props; }

參考:
IOS
遍歷未知對(duì)象的屬性和方法

然后我們提取出我們需要的, 圖標(biāo)和應(yīng)用名逗物。
[appsInfoArr enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { NSDictionary *boundIconsDictionary = [obj performSelector:@selector(boundIconsDictionary)]; NSString *iconPath = [NSString stringWithFormat:@"%@/%@.png", [[obj performSelector:@selector(resourcesDirectoryURL)] path], [[[boundIconsDictionary objectForKey:@"CFBundlePrimaryIcon"] objectForKey:@"CFBundleIconFiles"]lastObject]]; UIImage *image = [[[UIImage alloc]initWithContentsOfFile:iconPath] TransformtoSize:CGSizeMake(65, 65)]; if (image) { [self.appsIconArr addObject:image]; [self.appsNameArr addObject:[obj performSelector:@selector(localizedName)]]; } }];

如此, _self.appsIconArr

_appsNameArr
中存儲(chǔ)的就是我們需要的App數(shù)據(jù)了。

越獄
.. 這里我也不懂, 也沒(méi)去研究瑟俭。 感興趣的可以看看
MobileInstallation.framework

掃描動(dòng)畫(huà)的實(shí)現(xiàn)
這里主要有兩個(gè)動(dòng)畫(huà)翎卓。
利用UIScrollView, 實(shí)現(xiàn)每個(gè)App自動(dòng)滾動(dòng)。
Animation動(dòng)畫(huà), 中間掃描線的往返運(yùn)動(dòng)摆寄。

至于動(dòng)畫(huà), 這里我不想介紹太多失暴。 源碼里面都寫(xiě)清楚了。(當(dāng)然, 寫(xiě)的比較粗糙…)
簡(jiǎn)單帶一下掃描線的動(dòng)畫(huà)實(shí)現(xiàn):
/* 向左移動(dòng) */ CABasicAnimation animationLeft = [CABasicAnimation animationWithKeyPath:@"transform.translation.x"]; // 動(dòng)畫(huà)選項(xiàng)的設(shè)定 animationLeft.duration = 0.5f; // 持續(xù)時(shí)間 animationLeft.beginTime = 0.0f; animationLeft.autoreverses = YES; // 結(jié)束后執(zhí)行逆動(dòng)畫(huà) // 動(dòng)畫(huà)先加速后減速 animationLeft.timingFunction = [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseInEaseOut]; // 終了幀 animationLeft.toValue = [NSNumber numberWithFloat:-40];; / 向右移動(dòng) */ CABasicAnimation animationRight = [CABasicAnimation animationWithKeyPath:@"transform.translation.x"]; // 動(dòng)畫(huà)選項(xiàng)的設(shè)定 animationRight.duration = 0.5f; // 持續(xù)時(shí)間 animationRight.beginTime = 1.0f; animationRight.autoreverses = YES; // 結(jié)束后執(zhí)行逆動(dòng)畫(huà) // 動(dòng)畫(huà)先加速后減速 animationRight.timingFunction = [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseInEaseOut]; // 終了幀 animationRight.toValue = [NSNumber numberWithFloat:40];; / 動(dòng)畫(huà)組 */ CAAnimationGroup *group = [CAAnimationGroup animation]; group.delegate = self; group.duration = 2.0; group.repeatCount = 15; // 動(dòng)畫(huà)結(jié)束后不變回初始狀態(tài) group.removedOnCompletion = NO; group.fillMode = kCAFillModeForwards; // 添加動(dòng)畫(huà) group.animations = [NSArray arrayWithObjects:animationLeft, animationRight, nil]; [mySL.layer addAnimation:group forKey:@"moveLeft-moveRight-layer"];

獲取已用存儲(chǔ)和可用存儲(chǔ)
這個(gè)沒(méi)什么好說(shuō)的了.. Apple提供了API, 直接用就是了微饥。
// 獲取占用內(nèi)存-(void)usedSpaceAndfreeSpace{ NSString* path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] ; NSFileManager* fileManager = [[NSFileManager alloc ]init]; NSDictionary *fileSysAttributes = [fileManager attributesOfFileSystemForPath:path error:nil]; NSNumber *freeSpace = [fileSysAttributes objectForKey:NSFileSystemFreeSize]; NSNumber *totalSpace = [fileSysAttributes objectForKey:NSFileSystemSize]; NSString * str= [NSString stringWithFormat:@"已占用%0.1f G / 剩余%0.1f MB",([totalSpace longLongValue] - [freeSpace longLongValue])/1024.0/1024.0/1024.0,[freeSpace longLongValue]/1024.0/1024.0]; NSLog(@"--------%@",str);}

垃圾清理
這里我本來(lái)是不想提的逗扒,畢竟這個(gè)功能,蘋(píng)果是不能接受的欠橘。
之前提到了, 獵豹在清理過(guò)程中,
會(huì)出現(xiàn) “存儲(chǔ)已滿的提示”
矩肩。然后我開(kāi)始考慮了。

為什么要彈出提示肃续?
存儲(chǔ)真的在某一刻滿了嗎黍檩?
它清理的時(shí)候, QQ直接被殺死, 應(yīng)用名變成”正在清理…”(和安裝中一個(gè)狀態(tài))。 真有這么厲害? !!!!!!
這個(gè)好像在哪里見(jiàn)過(guò)…

最后,我確定了獵豹的實(shí)現(xiàn)方式始锚。它只不過(guò)是觸發(fā)了Apple自己的垃圾回收機(jī)制而已刽酱。
當(dāng)存儲(chǔ)滿的時(shí)候, 系統(tǒng)會(huì)自動(dòng)幫我們進(jìn)行垃圾清理, 并彈出提示說(shuō)明存儲(chǔ)已滿。

所以, 獵豹只不過(guò)是計(jì)算了剩余多少存儲(chǔ),
然后制造了一個(gè)與之差不多大小的垃圾文件瞧捌。
然后觸發(fā)蘋(píng)果的清理機(jī)制棵里。清理完后,
刪除之前生成的垃圾文件。再次統(tǒng)計(jì)當(dāng)前可用存儲(chǔ),
差值即為本次清理的垃圾大小姐呐。

是吧, 其實(shí)也沒(méi)那么神~
至于如何快速制造幾百M(fèi), 甚至幾G的垃圾文件?
// 將文件的長(zhǎng)度設(shè)定為offset -(void)truncateFileAtOffset:offset

truncateFileAtOffset:offset
就能搞定了殿怜。 感興趣的可以自己研究下。
至此, 獵豹垃圾清理分析完畢皮钠。
當(dāng)然, 這只是我個(gè)人的看法稳捆。如果有更好的方式, 或者文章中存在任何錯(cuò)誤。歡迎交流指正麦轰。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末乔夯,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子款侵,更是在濱河造成了極大的恐慌末荐,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件新锈,死亡現(xiàn)場(chǎng)離奇詭異甲脏,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)块请,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)娜氏,“玉大人,你說(shuō)我怎么就攤上這事墩新∶趁郑” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵海渊,是天一觀的道長(zhǎng)绵疲。 經(jīng)常有香客問(wèn)我,道長(zhǎng)臣疑,這世上最難降的妖魔是什么盔憨? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮讯沈,結(jié)果婚禮上郁岩,老公的妹妹穿的比我還像新娘。我一直安慰自己芙盘,他們只是感情好驯用,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著儒老,像睡著了一般蝴乔。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上驮樊,一...
    開(kāi)封第一講書(shū)人閱讀 51,562評(píng)論 1 305
  • 那天薇正,我揣著相機(jī)與錄音,去河邊找鬼囚衔。 笑死挖腰,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的练湿。 我是一名探鬼主播猴仑,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼肥哎!你這毒婦竟也來(lái)了辽俗?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤篡诽,失蹤者是張志新(化名)和其女友劉穎崖飘,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體杈女,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡朱浴,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年吊圾,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片翰蠢。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡项乒,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出梁沧,到底是詐尸還是另有隱情板丽,我是刑警寧澤,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布趁尼,位于F島的核電站,受9級(jí)特大地震影響猖辫,放射性物質(zhì)發(fā)生泄漏酥泞。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一啃憎、第九天 我趴在偏房一處隱蔽的房頂上張望芝囤。 院中可真熱鬧,春花似錦辛萍、人聲如沸悯姊。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)悯许。三九已至,卻和暖如春辉阶,著一層夾襖步出監(jiān)牢的瞬間先壕,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工谆甜, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留垃僚,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓规辱,卻偏偏與公主長(zhǎng)得像谆棺,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子罕袋,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容