Commit 0d6a6274 authored by wanglei's avatar wanglei

...

parent 78d5d7bc
......@@ -136,6 +136,11 @@ dependencies {
//work
implementation("androidx.work:work-runtime-ktx:2.7.1") // 请使用最新版本
implementation("com.github.pokercc:ExpandableRecyclerView:0.9.3")
implementation("com.github.bumptech.glide:glide:4.16.0")
annotationProcessor("com.github.bumptech.glide:glide:4.16.0")
}
......@@ -19,9 +19,9 @@
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/logo"
android:label="@string/app_name"
android:largeHeap="true"
android:requestLegacyExternalStorage="true"
android:roundIcon="@mipmap/logo"
android:largeHeap="true"
android:supportsRtl="true"
android:theme="@style/Theme.PDFViewerScannerWhite"
android:usesCleartextTraffic="true"
......@@ -179,6 +179,37 @@
android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
<activity
android:name=".mix.ScreenshotCleanActivity"
android:exported="false"
android:launchMode="singleTop"
android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
<activity
android:name=".mix.SimilarPhotosActivity"
android:exported="false"
android:launchMode="singleTop"
android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
<activity
android:name=".mix.WhatsappCleanActivity"
android:exported="false"
android:launchMode="singleTop"
android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
<activity
android:name=".mix.WhatsappCleanDetailActivity"
android:exported="false"
android:launchMode="singleTop"
android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
<activity
android:name=".mix.LargeFileCleanActivity"
android:exported="false"
android:launchMode="singleTop"
android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
......
{"v":"5.6.3","fr":25,"ip":0,"op":36,"w":870,"h":870,"nm":"1-扫描动画","ddd":0,"assets":[{"id":"image_0","w":120,"h":120,"u":"images/","p":"img_0.png","e":0},{"id":"image_1","w":198,"h":198,"u":"images/","p":"img_1.png","e":0},{"id":"image_2","w":678,"h":678,"u":"images/","p":"img_2.png","e":0},{"id":"image_3","w":678,"h":678,"u":"images/","p":"img_3.png","e":0}],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"小飞圆","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":20,"s":[60],"e":[0]},{"t":40}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":20,"s":[141,893,0],"e":[437,429,0],"to":[0,0,0],"ti":[0,0,0]},{"t":35}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[16,16],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"小飞圆","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":75,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"小飞圆","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.8],"y":[1]},"o":{"x":[0.2],"y":[0]},"t":5,"s":[60],"e":[0]},{"t":25}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.8,"y":1},"o":{"x":0.2,"y":0},"t":5,"s":[892,226,0],"e":[462,460,0],"to":[0,0,0],"ti":[0,0,0]},{"t":20}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[16,16],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"小飞圆","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":75,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"小飞圆","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.8],"y":[1]},"o":{"x":[0.2],"y":[0]},"t":5,"s":[60],"e":[0]},{"t":25}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.8,"y":1},"o":{"x":0.2,"y":0},"t":5,"s":[-81,761,0],"e":[431,435,0],"to":[0,0,0],"ti":[0,0,0]},{"t":30}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[22,22],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"小飞圆","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":75,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"小飞圆","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.8],"y":[1]},"o":{"x":[0.2],"y":[0]},"t":10,"s":[60],"e":[0]},{"t":30}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.8,"y":1},"o":{"x":0.2,"y":0},"t":10,"s":[574,-48,0],"e":[434,408,0],"to":[0,0,0],"ti":[0,0,0]},{"t":30}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[20,20],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"小飞圆","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":75,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"小飞圆","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.8],"y":[1]},"o":{"x":[0.2],"y":[0]},"t":0,"s":[60],"e":[0]},{"t":20}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.8,"y":1},"o":{"x":0.2,"y":0},"t":0,"s":[-48,-40,0],"e":[444,444,0],"to":[0,0,0],"ti":[0,0,0]},{"t":18}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[36,36],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"小飞圆","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":75,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"小飞圆","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.2],"y":[0]},"t":16,"s":[60],"e":[0]},{"t":36}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.8,"y":1},"o":{"x":0.2,"y":0},"t":16,"s":[1018,824,0],"e":[446,462,0],"to":[0,0,0],"ti":[0,0,0]},{"t":31}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[26,26],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"小飞圆","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":75,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":2,"nm":"icon_clean_home","refId":"image_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[435,435,0],"ix":2},"a":{"a":0,"k":[60,60,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":75,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":2,"nm":"小圆","refId":"image_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[435,435,0],"ix":2},"a":{"a":0,"k":[99,99,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":75,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":2,"nm":"转圈园","refId":"image_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0],"e":[360]},{"t":35}],"ix":10},"p":{"a":0,"k":[435,435,0],"ix":2},"a":{"a":0,"k":[339,339,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":75,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":2,"nm":"背景圆","refId":"image_3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[435,435,0],"ix":2},"a":{"a":0,"k":[339,339,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":75,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file
{"v":"5.6.3","fr":25,"ip":0,"op":36,"w":870,"h":870,"nm":"1-扫描动画","ddd":0,"assets":[{"id":"image_0","w":120,"h":120,"u":"images/","p":"img_0.png","e":0},{"id":"image_1","w":198,"h":198,"u":"images/","p":"img_1.png","e":0},{"id":"image_2","w":678,"h":678,"u":"images/","p":"img_2.png","e":0},{"id":"image_3","w":678,"h":678,"u":"images/","p":"img_3.png","e":0}],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"小飞圆","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":20,"s":[60],"e":[0]},{"t":40}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":20,"s":[141,893,0],"e":[437,429,0],"to":[0,0,0],"ti":[0,0,0]},{"t":35}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[16,16],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"小飞圆","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":75,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"小飞圆","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.8],"y":[1]},"o":{"x":[0.2],"y":[0]},"t":5,"s":[60],"e":[0]},{"t":25}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.8,"y":1},"o":{"x":0.2,"y":0},"t":5,"s":[892,226,0],"e":[462,460,0],"to":[0,0,0],"ti":[0,0,0]},{"t":20}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[16,16],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"小飞圆","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":75,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"小飞圆","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.8],"y":[1]},"o":{"x":[0.2],"y":[0]},"t":5,"s":[60],"e":[0]},{"t":25}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.8,"y":1},"o":{"x":0.2,"y":0},"t":5,"s":[-81,761,0],"e":[431,435,0],"to":[0,0,0],"ti":[0,0,0]},{"t":30}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[22,22],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"小飞圆","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":75,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"小飞圆","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.8],"y":[1]},"o":{"x":[0.2],"y":[0]},"t":10,"s":[60],"e":[0]},{"t":30}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.8,"y":1},"o":{"x":0.2,"y":0},"t":10,"s":[574,-48,0],"e":[434,408,0],"to":[0,0,0],"ti":[0,0,0]},{"t":30}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[20,20],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"小飞圆","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":75,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"小飞圆","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.8],"y":[1]},"o":{"x":[0.2],"y":[0]},"t":0,"s":[60],"e":[0]},{"t":20}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.8,"y":1},"o":{"x":0.2,"y":0},"t":0,"s":[-48,-40,0],"e":[444,444,0],"to":[0,0,0],"ti":[0,0,0]},{"t":18}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[36,36],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"小飞圆","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":75,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"小飞圆","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.2],"y":[0]},"t":16,"s":[60],"e":[0]},{"t":36}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.8,"y":1},"o":{"x":0.2,"y":0},"t":16,"s":[1018,824,0],"e":[446,462,0],"to":[0,0,0],"ti":[0,0,0]},{"t":31}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[26,26],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"小飞圆","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":75,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":2,"nm":"icon_clean_home","refId":"image_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[435,435,0],"ix":2},"a":{"a":0,"k":[60,60,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":75,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":2,"nm":"小圆","refId":"image_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[435,435,0],"ix":2},"a":{"a":0,"k":[99,99,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":75,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":2,"nm":"转圈园","refId":"image_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0],"e":[360]},{"t":35}],"ix":10},"p":{"a":0,"k":[435,435,0],"ix":2},"a":{"a":0,"k":[339,339,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":75,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":2,"nm":"背景圆","refId":"image_3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[435,435,0],"ix":2},"a":{"a":0,"k":[339,339,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":75,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file
{"v":"5.6.3","fr":25,"ip":0,"op":36,"w":870,"h":870,"nm":"1-扫描动画","ddd":0,"assets":[{"id":"image_0","w":120,"h":120,"u":"images/","p":"img_0.png","e":0},{"id":"image_1","w":198,"h":198,"u":"images/","p":"img_1.png","e":0},{"id":"image_2","w":678,"h":678,"u":"images/","p":"img_2.png","e":0},{"id":"image_3","w":678,"h":678,"u":"images/","p":"img_3.png","e":0}],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"小飞圆","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":20,"s":[60],"e":[0]},{"t":40}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":20,"s":[141,893,0],"e":[437,429,0],"to":[0,0,0],"ti":[0,0,0]},{"t":35}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[16,16],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"小飞圆","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":75,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"小飞圆","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.8],"y":[1]},"o":{"x":[0.2],"y":[0]},"t":5,"s":[60],"e":[0]},{"t":25}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.8,"y":1},"o":{"x":0.2,"y":0},"t":5,"s":[892,226,0],"e":[462,460,0],"to":[0,0,0],"ti":[0,0,0]},{"t":20}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[16,16],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"小飞圆","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":75,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"小飞圆","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.8],"y":[1]},"o":{"x":[0.2],"y":[0]},"t":5,"s":[60],"e":[0]},{"t":25}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.8,"y":1},"o":{"x":0.2,"y":0},"t":5,"s":[-81,761,0],"e":[431,435,0],"to":[0,0,0],"ti":[0,0,0]},{"t":30}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[22,22],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"小飞圆","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":75,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"小飞圆","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.8],"y":[1]},"o":{"x":[0.2],"y":[0]},"t":10,"s":[60],"e":[0]},{"t":30}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.8,"y":1},"o":{"x":0.2,"y":0},"t":10,"s":[574,-48,0],"e":[434,408,0],"to":[0,0,0],"ti":[0,0,0]},{"t":30}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[20,20],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"小飞圆","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":75,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"小飞圆","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.8],"y":[1]},"o":{"x":[0.2],"y":[0]},"t":0,"s":[60],"e":[0]},{"t":20}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.8,"y":1},"o":{"x":0.2,"y":0},"t":0,"s":[-48,-40,0],"e":[444,444,0],"to":[0,0,0],"ti":[0,0,0]},{"t":18}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[36,36],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"小飞圆","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":75,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"小飞圆","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.2],"y":[0]},"t":16,"s":[60],"e":[0]},{"t":36}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.8,"y":1},"o":{"x":0.2,"y":0},"t":16,"s":[1018,824,0],"e":[446,462,0],"to":[0,0,0],"ti":[0,0,0]},{"t":31}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[26,26],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"小飞圆","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":75,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":2,"nm":"icon_clean_home","refId":"image_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[435,435,0],"ix":2},"a":{"a":0,"k":[60,60,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":75,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":2,"nm":"小圆","refId":"image_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[435,435,0],"ix":2},"a":{"a":0,"k":[99,99,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":75,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":2,"nm":"转圈园","refId":"image_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0],"e":[360]},{"t":35}],"ix":10},"p":{"a":0,"k":[435,435,0],"ix":2},"a":{"a":0,"k":[339,339,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":75,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":2,"nm":"背景圆","refId":"image_3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[435,435,0],"ix":2},"a":{"a":0,"k":[339,339,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":75,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file
{"v":"5.6.3","fr":25,"ip":0,"op":36,"w":870,"h":870,"nm":"1-扫描动画","ddd":0,"assets":[{"id":"image_0","w":120,"h":120,"u":"images/","p":"img_0.png","e":0},{"id":"image_1","w":198,"h":198,"u":"images/","p":"img_1.png","e":0},{"id":"image_2","w":678,"h":678,"u":"images/","p":"img_2.png","e":0},{"id":"image_3","w":678,"h":678,"u":"images/","p":"img_3.png","e":0}],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"小飞圆","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":20,"s":[60],"e":[0]},{"t":40}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":20,"s":[141,893,0],"e":[437,429,0],"to":[0,0,0],"ti":[0,0,0]},{"t":35}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[16,16],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"小飞圆","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":75,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"小飞圆","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.8],"y":[1]},"o":{"x":[0.2],"y":[0]},"t":5,"s":[60],"e":[0]},{"t":25}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.8,"y":1},"o":{"x":0.2,"y":0},"t":5,"s":[892,226,0],"e":[462,460,0],"to":[0,0,0],"ti":[0,0,0]},{"t":20}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[16,16],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"小飞圆","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":75,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"小飞圆","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.8],"y":[1]},"o":{"x":[0.2],"y":[0]},"t":5,"s":[60],"e":[0]},{"t":25}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.8,"y":1},"o":{"x":0.2,"y":0},"t":5,"s":[-81,761,0],"e":[431,435,0],"to":[0,0,0],"ti":[0,0,0]},{"t":30}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[22,22],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"小飞圆","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":75,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"小飞圆","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.8],"y":[1]},"o":{"x":[0.2],"y":[0]},"t":10,"s":[60],"e":[0]},{"t":30}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.8,"y":1},"o":{"x":0.2,"y":0},"t":10,"s":[574,-48,0],"e":[434,408,0],"to":[0,0,0],"ti":[0,0,0]},{"t":30}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[20,20],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"小飞圆","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":75,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"小飞圆","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.8],"y":[1]},"o":{"x":[0.2],"y":[0]},"t":0,"s":[60],"e":[0]},{"t":20}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.8,"y":1},"o":{"x":0.2,"y":0},"t":0,"s":[-48,-40,0],"e":[444,444,0],"to":[0,0,0],"ti":[0,0,0]},{"t":18}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[36,36],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"小飞圆","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":75,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"小飞圆","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.2],"y":[0]},"t":16,"s":[60],"e":[0]},{"t":36}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.8,"y":1},"o":{"x":0.2,"y":0},"t":16,"s":[1018,824,0],"e":[446,462,0],"to":[0,0,0],"ti":[0,0,0]},{"t":31}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[26,26],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"小飞圆","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":75,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":2,"nm":"icon_clean_home","refId":"image_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[435,435,0],"ix":2},"a":{"a":0,"k":[60,60,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":75,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":2,"nm":"小圆","refId":"image_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[435,435,0],"ix":2},"a":{"a":0,"k":[99,99,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":75,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":2,"nm":"转圈园","refId":"image_2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0],"e":[360]},{"t":35}],"ix":10},"p":{"a":0,"k":[435,435,0],"ix":2},"a":{"a":0,"k":[339,339,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":75,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":2,"nm":"背景圆","refId":"image_3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[435,435,0],"ix":2},"a":{"a":0,"k":[339,339,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"ip":0,"op":75,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file
......@@ -61,6 +61,7 @@ object ConstObject {
const val FUNCTION_SCAM_JUNK = "function_scam_junk"
const val FUNCTION_APP_PROCESS = "function_app_process"
const val FUNCTION_SCREEN_SHORT = "function_app_screen"
var ifAgreePrivacy = false
get() {
......
package com.base.pdfviewerscannerwhite.bean
class FunctionUIBean(
val key: String = "",
val icon: Int = 0,
val desc: String = "",
) {
companion object {
const val KEY_PROCESS = "key_process"
const val KEY_FILE_MANAGER = "key_file_manager"
const val KEY_MERGE = "key_merge"
const val KEY_SPLIT = "key_split"
const val KEY_SCAN = "key_scan"
const val KEY_LOCK = "key_lock"
const val KEY_UNLOCK = "key_unlock"
const val KEY_IMAGE = "key_image"
const val KEY_SCREENSHOT = "key_screenshot"
const val KEY_SIMILAR = "key_similar"
const val KEY_WHATSAPP = "key_whatsapp"
const val KEY_LARGE_FILE = "key_large_file"
}
}
\ No newline at end of file
package com.base.pdfviewerscannerwhite.bean
data class SimilarBean(
val url: String,
val hashCode: String,
val avgPixel: Int,
val size: Long,
var isSelect: Boolean,
var items: MutableList<SimilarBean> = mutableListOf()
)
\ No newline at end of file
package com.base.pdfviewerscannerwhite.mix
import android.content.Context
import com.base.pdfviewerscannerwhite.utils.ActivityLauncher
object ActivityJumpHelps {
private var isShowStoragePermission = false
fun start(
context: Context,
launcher: ActivityLauncher,
nameId: Int
) {
when(nameId) {
// R.string.junk_scan -> requestPermission(context, launcher) { CleanJunkActivity.start(context) }
// R.string.app_process -> AppProcessActivity.start(context)
// R.string.whatsapp_clean -> requestPermission(context, launcher) { WhatsappCleanActivity.start(context) }
// R.string.screenshot_clean -> requestPermission(context, launcher) { ScreenshotCleanActivity.start(context) }
// R.string.similar_photos -> requestPermission(context, launcher) { com.base.pdfviewerscannerwhite.mix.SimilarPhotosActivity.start(context) }
}
}
fun startFunction(
context: Context,
launcher: ActivityLauncher,
notificationId: Int
) {
when (notificationId) {
// ID_CLEAN_JUNK -> requestPermission(context, launcher) { CleanJunkActivity.start(context) }
// ID_WHATSAPP -> requestPermission(context, launcher) { com.base.scanqrclear.luma.WhatsappCleanActivity.start(context) }
// ID_LARGE_FILE_CLEANER -> requestPermission(context, launcher) { com.base.pdfviewerscannerwhite.mix.LargeFileCleanActivity.start(context) }
// ID_PHOTO_COMPRESSION -> requestPermission(context, launcher) { PhotoCompressionActivity.start(context) }
// ID_SCREENSHOT_CLEAN -> requestPermission(context, launcher) { ScreenshotCleanActivity.start(context) }
}
}
fun requestPermission(
context: Context,
launcher: ActivityLauncher,
block: (() -> Unit)? = null
) {
if (PermissionHelps.checkFilesAccessPermission(context)) {
block?.invoke()
} else {
if (isShowStoragePermission) return
isShowStoragePermission = true
DialogHelps.showStoragePermissionDialog(
context,
{
PermissionHelps.requestFilesAccessPermission(context, launcher, result = {
if (it) block?.invoke()
isShowStoragePermission = false
})
},
{
isShowStoragePermission = false
}
)
}
}
}
\ No newline at end of file
package com.base.pdfviewerscannerwhite.mix
import android.app.Activity
import java.util.Stack
object ActivityManagerHelps {
private val activityStack = Stack<Activity>()
/**
* 添加Activity到堆栈
*/
fun add(activity: Activity) {
activityStack.add(activity)
}
/**
* 移除Activity从堆栈
*/
fun remove(activity: Activity) {
activityStack.remove(activity)
}
/**
* 结束指定的Activity
*/
fun finish(activity: Activity?) {
if (activity != null) {
activityStack.remove(activity)
activity.finish()
}
}
/**
* 结束所有Activity
*/
fun finishAll() {
for (activity in activityStack) {
activity?.finish()
}
activityStack.clear()
}
fun finishAll(excludeCls: Class<*>?) {
val iterator = activityStack.iterator()
while (iterator.hasNext()) {
val item = iterator.next()
if (excludeCls != item.javaClass) {
item.finish()
iterator.remove()
}
}
}
/**
* 检查Activity是否存在于堆栈中
*/
fun isActivityInStack(cls: Class<*>?): Boolean {
var isExist = false
if (cls != null) {
for (activity in activityStack) {
if (cls == activity.javaClass) {
isExist = true
break
}
}
}
return isExist
}
val all: List<Activity>
get() = activityStack
val topActivity: Activity?
get() = if (activityStack.isEmpty()) {
null
} else {
activityStack.peek()
}
}
\ No newline at end of file
package com.base.pdfviewerscannerwhite.mix
import android.app.Activity
import android.content.Context
import android.os.Bundle
import android.util.Log
import android.view.ViewGroup
import android.view.ViewTreeObserver
import com.applovin.mediation.MaxAd
import com.applovin.mediation.MaxAdListener
import com.applovin.mediation.MaxAdViewAdListener
import com.applovin.mediation.MaxError
import com.applovin.mediation.ads.MaxAdView
import com.applovin.mediation.ads.MaxAppOpenAd
import com.applovin.mediation.ads.MaxInterstitialAd
import com.applovin.mediation.nativeAds.MaxNativeAdListener
import com.applovin.mediation.nativeAds.MaxNativeAdLoader
import com.applovin.mediation.nativeAds.MaxNativeAdView
import com.applovin.sdk.AppLovinMediationProvider
import com.applovin.sdk.AppLovinSdk
import com.applovin.sdk.AppLovinSdkInitializationConfiguration
import com.base.pdfviewerscannerwhite.helper.ConfigHelper
import com.google.ads.mediation.admob.AdMobAdapter
import com.google.android.gms.ads.AdError
import com.google.android.gms.ads.AdListener
import com.google.android.gms.ads.AdLoader
import com.google.android.gms.ads.AdRequest
import com.google.android.gms.ads.AdSize
import com.google.android.gms.ads.AdView
import com.google.android.gms.ads.FullScreenContentCallback
import com.google.android.gms.ads.LoadAdError
import com.google.android.gms.ads.appopen.AppOpenAd
import com.google.android.gms.ads.interstitial.InterstitialAd
import com.google.android.gms.ads.interstitial.InterstitialAdLoadCallback
import com.google.android.gms.ads.nativead.NativeAd
import com.google.android.gms.ads.nativead.NativeAdOptions
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
import java.util.UUID
object AdmobHelps {
//
const val KEY_INIT = "key_init"
const val KEY_AD = "sAd"
const val KEY_BLACKLIST = "blacklist"
const val KEY_REFERRER = "referrer"
const val KEY_UUID = "key_uuid"
const val KEY_GOOGLE_ADVERTISER_ID = "key_google_advertiser_id"
const val KEY_DEVICE_NAME = "key_device_name"
const val KEY_INSTALL_TIME = "key_install_time"
const val KEY_CLEAN_LAST_TIME = "key_clean_last_time"
const val KEY_CLEANUP_SIZE = "key_cleanup_size"
const val KEY_NOT_CLEAN_TIME = "key_not_clean_time"
const val KEY_NOTIFICATION_ID = "key_notification_id"
const val KEY_APP_BACKGROUND = "key_app_background"
const val KEY_HOME_COUNT = "key_home_count"
const val KEY_DEVICE_SCAN = "key_device_scan"
const val KEY_SCORE = "key_score"
const val ID_CLEAN_JUNK = 31000
const val ID_WHATSAPP = 31010
const val ID_BATTERY_INFO = 31020
const val ID_LARGE_FILE_CLEANER = 31030
const val ID_PHOTO_COMPRESSION = 31040
const val ID_SCREENSHOT_CLEAN = 31050
const val ID_APP_INSTALL = 31060
const val ID_APP_UNINSTALL = 31070
const val ID_NOT_CLEANED = 31080
const val ID_BATTERY_LEVEL = 31090
const val ID_APP_MANAGER = 31100
const val ID_HOME = 31200
private const val APP_OPEN_AD_UNIT = "openAd"
private const val INTERSTITIAL_AD_UNIT = "interAd"
private const val NATIVE_AD_UNIT = "nativeAd"
private const val NO_AD = "no_ad"
private const val KEY_AD_INTERVAL = "adInterval"
private const val KEY_AD_REQUEST = "adRequest"
private const val KEY_AD_CLICK = "adClick"
private const val KEY_AD_SHOW = "adShow"
private const val KEY_IS_SHOW_AD_BANNER = "isShowAdBanner"
private const val KEY_IS_SHOW_AD_NATIVE = "isShowAdNative"
private const val KEY_IS_SHOW_AD_INTER = "isShowAdInter"
private const val KEY_IS_SHOW_AD_BACK_INTER = "isShowAdBackInter"
private const val KEY_IS_SHOW_AD_RESULT_BACK_INTER = "isShowAdResultBackInter"
private const val DEFAULT_AD_INTERVAL = 0
private const val DEFAULT_AD_REQUEST = 100
private const val DEFAULT_AD_CLICK = 10
private const val DEFAULT_AD_SHOW = 45
private const val KEY_DISPLAY_NUMBER = "key_display_number"
private const val KEY_REQUEST_NUMBER = "key_request_number"
private const val KEY_CLICK_NUMBER = "key_click_number"
private const val KEY_LAST_DISPLAY_TIME = "key_last_display_time"
private const val EVENT_BLACKLIST = "blacklist"
private const val EVENT_SHOW_DISPLAYS = "showDisPlays"
private const val EVENT_SHOW_REQUESTS = "showRequests"
private const val EVENT_SHOW_CLICKS = "showClicks"
private const val EVENT_SHOW_INTERVAL_TIME = "showIntervalTime"
//
private const val TAG = "AdmobHelps"
private var appOpenAd: AppOpenAd? = null
private var appOpenMaxAd: MaxAppOpenAd? = null
private var appOpenAdLoadTime: Long = 0
private var interstitialAd: InterstitialAd? = null
private var interstitialMaxAd: MaxInterstitialAd? = null
private var interstitialAdLoadTime: Long = 0
var isLoadingAppOpenAd = false
var isLoadingInterstitialAd = false
private var lastShowTime: Long = 0
var blacklist = 1
private var showTime
get() = SpUtils.getInstance()
.getLong(KEY_LAST_DISPLAY_TIME, System.currentTimeMillis())
set(value) = SpUtils.getInstance().putLong(KEY_LAST_DISPLAY_TIME, value)
inline var useAdmob
get() = SpUtils.getInstance().getBoolean("sAd", true)
set(value) = SpUtils.getInstance().putBoolean("sAd", value)
fun init(
context: Context,
loaded: (Int) -> Unit,
failed: () -> Unit,
) {
if (isBlacklist()) {
failed.invoke()
return
}
if (useAdmob) {
if (isAppOpenAdAvailable()) {
loaded.invoke(0)
return
}
if (isInterstitialAdAvailable()) {
loaded.invoke(1)
loadAppOpenAd(context)
return
}
loadAppOpenAd(context, { loaded.invoke(0) }, { failed.invoke() })
} else {
val initConfig = AppLovinSdkInitializationConfiguration.builder(
"", context
).setMediationProvider(AppLovinMediationProvider.MAX).build()
AppLovinSdk.getInstance(context).initialize(initConfig) {
if (isAppOpenAdAvailable()) {
loaded.invoke(0)
return@initialize
}
if (isInterstitialAdAvailable()) {
loaded.invoke(1)
loadAppOpenAd(context)
return@initialize
}
loadAppOpenAd(context, { loaded.invoke(0) }, { failed.invoke() })
}
}
}
fun loadAppOpenAd(
context: Context,
loaded: (() -> Unit?)? = null,
failed: (() -> Unit?)? = null,
) {
if (!checkAvailable(APP_OPEN_AD_UNIT)) {
failed?.invoke()
return
}
if (isLoadingAppOpenAd) {
// failed?.invoke()
return
}
isLoadingAppOpenAd = true
Log.d(TAG, "app open Ad load.")
val reqId = UUID.randomUUID().toString()
ReportAdUtils.pullStartAd(reqId, APP_OPEN_AD_UNIT, (context as Activity).javaClass.simpleName)
if (useAdmob) {
val adRequest = AdRequest.Builder().build()
AppOpenAd.load(
context,
ConfigHelper.openAdmobId,
adRequest,
object : AppOpenAd.AppOpenAdLoadCallback() {
override fun onAdFailedToLoad(loadAdError: LoadAdError) {
Log.d(TAG, "app open failed to load: ${loadAdError.message}")
isLoadingAppOpenAd = false
failed?.invoke()
ReportAdUtils.pullAd(
loadAdError.responseInfo,
APP_OPEN_AD_UNIT,
loadAdError.message,
reqId
)
}
override fun onAdLoaded(ad: AppOpenAd) {
Log.d(TAG, "app open Ad was loaded.")
appOpenAd = ad
appOpenAdLoadTime = System.currentTimeMillis()
isLoadingAppOpenAd = false
loaded?.invoke()
calculate(KEY_REQUEST_NUMBER)
ReportAdUtils.pullAd(ad.responseInfo, APP_OPEN_AD_UNIT, reqId = reqId)
ad.onPaidEventListener = ReportAdUtils.EventOnPaidEventListener(ad)
}
})
} else {
appOpenMaxAd = MaxAppOpenAd(ConfigHelper.openAdmobId, context)
appOpenMaxAd?.setListener(object : MaxAdListener {
override fun onAdLoaded(ad: MaxAd) {
Log.d(TAG, "app open Ad Max was loaded.")
appOpenAdLoadTime = System.currentTimeMillis()
loaded?.invoke()
calculate(KEY_REQUEST_NUMBER)
isLoadingAppOpenAd = false
}
override fun onAdDisplayed(p0: MaxAd) {
}
override fun onAdHidden(p0: MaxAd) {
}
override fun onAdClicked(p0: MaxAd) {
}
override fun onAdLoadFailed(p0: String, p1: MaxError) {
Log.d(TAG, "app open Max failed to load: $p0 ${p1.message}")
isLoadingAppOpenAd = false
failed?.invoke()
}
override fun onAdDisplayFailed(p0: MaxAd, p1: MaxError) {
}
})
appOpenMaxAd?.loadAd()
}
}
fun loadInterstitialAd(
context: Context,
loaded: (() -> Unit?)? = null,
failed: (() -> Unit?)? = null,
) {
if (!checkAvailable(INTERSTITIAL_AD_UNIT)) {
failed?.invoke()
return
}
if (isLoadingInterstitialAd) {
failed?.invoke()
return
}
isLoadingInterstitialAd = true
Log.d(TAG, "interstitial Ad load.")
val reqId = UUID.randomUUID().toString()
ReportAdUtils.pullStartAd(reqId, INTERSTITIAL_AD_UNIT, (context as Activity).javaClass.simpleName)
if (useAdmob) {
val adRequest = AdRequest.Builder().build()
InterstitialAd.load(
context,
ConfigHelper.interAdmobId,
adRequest,
object : InterstitialAdLoadCallback() {
override fun onAdFailedToLoad(loadAdError: LoadAdError) {
Log.d(TAG, "interstitial Ad failed to load: ${loadAdError.message}")
interstitialAd = null
isLoadingInterstitialAd = false
failed?.invoke()
ReportAdUtils.pullAd(
loadAdError.responseInfo,
INTERSTITIAL_AD_UNIT,
loadAdError.message,
reqId
)
}
override fun onAdLoaded(ad: InterstitialAd) {
Log.d(TAG, "interstitial Ad was loaded.")
interstitialAd = ad
interstitialAdLoadTime = System.currentTimeMillis()
isLoadingInterstitialAd = false
loaded?.invoke()
calculate(KEY_REQUEST_NUMBER)
ReportAdUtils.pullAd(ad.responseInfo, INTERSTITIAL_AD_UNIT, reqId = reqId)
ad.onPaidEventListener = ReportAdUtils.EventOnPaidEventListener(ad)
}
})
} else {
interstitialMaxAd = MaxInterstitialAd("", context)
interstitialMaxAd?.setListener(object : MaxAdListener {
override fun onAdLoaded(p0: MaxAd) {
Log.d(TAG, "interstitial Ad Max was loaded.")
interstitialAdLoadTime = System.currentTimeMillis()
isLoadingInterstitialAd = false
loaded?.invoke()
calculate(KEY_REQUEST_NUMBER)
}
override fun onAdDisplayed(p0: MaxAd) {
}
override fun onAdHidden(p0: MaxAd) {
}
override fun onAdClicked(p0: MaxAd) {
}
override fun onAdLoadFailed(p0: String, p1: MaxError) {
Log.d(TAG, "interstitial Ad failed to load: ${p1.message}")
interstitialMaxAd = null
isLoadingInterstitialAd = false
failed?.invoke()
}
override fun onAdDisplayFailed(p0: MaxAd, p1: MaxError) {
}
})
interstitialMaxAd?.loadAd()
}
}
fun showAppOpenAd(
activity: Activity,
dismissed: (() -> Unit?)? = null,
completed: (() -> Unit)? = null,
failed: (() -> Unit?)? = null,
isRetry: Boolean = false
) {
if (activity.isFinishing || activity.isDestroyed) return
if (!checkAvailable(APP_OPEN_AD_UNIT, true)) {
failed?.invoke()
return
}
if (!isRetry) ReportAdUtils.showPrepareAd(APP_OPEN_AD_UNIT)
if (!isAppOpenAdAvailable()) {
Log.d(TAG, "The app open ad is not ready yet.")
ReportAdUtils.limitErrorAd(NO_AD, APP_OPEN_AD_UNIT)
loadAppOpenAd(activity, {
showAppOpenAd(activity, dismissed, completed, failed, true)
}, {
failed?.invoke()
})
return
}
if (useAdmob) {
appOpenAd?.fullScreenContentCallback = object : FullScreenContentCallback() {
override fun onAdClicked() {
Log.d(TAG, "app open Ad was clicked")
calculate(KEY_CLICK_NUMBER)
ReportAdUtils.clickAd(appOpenAd?.responseInfo, APP_OPEN_AD_UNIT)
}
override fun onAdDismissedFullScreenContent() {
Log.d(TAG, "app open Ad dismissed fullscreen content.")
dismissed?.invoke()
}
override fun onAdFailedToShowFullScreenContent(adError: AdError) {
Log.d(TAG, "app open failed to show: ${adError.message}")
appOpenAd = null
failed?.invoke()
ReportAdUtils.showErrorAd(adError.message, APP_OPEN_AD_UNIT)
loadAppOpenAd(activity)
}
override fun onAdShowedFullScreenContent() {
Log.d(TAG, "app open Ad showed fullscreen content.")
lastShowTime = System.currentTimeMillis()
calculate(KEY_DISPLAY_NUMBER)
completed?.invoke()
ReportAdUtils.showAd(appOpenAd?.responseInfo, APP_OPEN_AD_UNIT, activity)
appOpenAd = null
loadAppOpenAd(activity)
}
}
appOpenAd?.show(activity)
} else {
appOpenMaxAd?.setListener(object : MaxAdListener {
override fun onAdLoaded(ad: MaxAd) {
}
override fun onAdDisplayed(p0: MaxAd) {
Log.d(TAG, "app open Ad Max showed fullscreen content.")
appOpenMaxAd = null
calculate(KEY_DISPLAY_NUMBER)
completed?.invoke()
loadAppOpenAd(activity)
}
override fun onAdHidden(p0: MaxAd) {
Log.d(TAG, "app open Ad Max dismissed fullscreen content.")
dismissed?.invoke()
}
override fun onAdClicked(p0: MaxAd) {
Log.d(TAG, "app open Ad Max was clicked")
calculate(KEY_CLICK_NUMBER)
}
override fun onAdLoadFailed(p0: String, p1: MaxError) {
}
override fun onAdDisplayFailed(p0: MaxAd, p1: MaxError) {
Log.d(TAG, "app open Max failed to show: ${p1.message}")
appOpenMaxAd = null
lastShowTime = System.currentTimeMillis()
failed?.invoke()
ReportAdUtils.showErrorAd(p1.message, APP_OPEN_AD_UNIT)
loadAppOpenAd(activity)
}
})
appOpenMaxAd?.showAd()
}
}
fun showInterstitialAd(
activity: Activity,
dismissed: (() -> Unit?)? = null,
completed: (() -> Unit)? = null,
failed: (() -> Unit?)? = null,
isRetry: Boolean = false
) {
if (activity.isFinishing || activity.isDestroyed) return
if (!checkAvailable(INTERSTITIAL_AD_UNIT, true)) {
failed?.invoke()
return
}
if (!isRetry) ReportAdUtils.showPrepareAd(INTERSTITIAL_AD_UNIT)
if (!isInterstitialAdAvailable()) {
Log.d(TAG, "The interstitial ad is not ready yet.")
ReportAdUtils.limitErrorAd(NO_AD, INTERSTITIAL_AD_UNIT)
loadInterstitialAd(activity, {
showInterstitialAd(activity, dismissed, completed, failed, true)
}, {
failed?.invoke()
})
return
}
if (useAdmob) {
interstitialAd?.fullScreenContentCallback = object : FullScreenContentCallback() {
override fun onAdClicked() {
Log.d(TAG, "interstitial Ad was clicked")
calculate(KEY_CLICK_NUMBER)
ReportAdUtils.clickAd(interstitialAd?.responseInfo, INTERSTITIAL_AD_UNIT)
}
override fun onAdDismissedFullScreenContent() {
Log.d(TAG, "interstitial Ad was dismissed.")
dismissed?.invoke()
}
override fun onAdFailedToShowFullScreenContent(adError: AdError) {
Log.d(TAG, "interstitial Ad failed to show: ${adError.message}")
interstitialAd = null
failed?.invoke()
ReportAdUtils.showErrorAd(adError.message, INTERSTITIAL_AD_UNIT)
loadInterstitialAd(activity)
}
override fun onAdShowedFullScreenContent() {
Log.d(TAG, "interstitial Ad showed fullscreen content.")
lastShowTime = System.currentTimeMillis()
calculate(KEY_DISPLAY_NUMBER)
completed?.invoke()
ReportAdUtils.showAd(
interstitialAd?.responseInfo,
INTERSTITIAL_AD_UNIT,
activity
)
interstitialAd = null
loadInterstitialAd(activity)
}
}
interstitialAd?.show(activity)
} else {
interstitialMaxAd?.setListener(object : MaxAdListener {
override fun onAdLoaded(p0: MaxAd) {
}
override fun onAdDisplayed(p0: MaxAd) {
Log.d(TAG, "interstitial Ad Max showed fullscreen content.")
calculate(KEY_DISPLAY_NUMBER)
completed?.invoke()
interstitialMaxAd = null
loadInterstitialAd(activity)
}
override fun onAdHidden(p0: MaxAd) {
Log.d(TAG, "interstitial Ad Max was dismissed.")
dismissed?.invoke()
}
override fun onAdClicked(p0: MaxAd) {
Log.d(TAG, "interstitial Ad Max was clicked")
calculate(KEY_CLICK_NUMBER)
}
override fun onAdLoadFailed(p0: String, p1: MaxError) {
}
override fun onAdDisplayFailed(p0: MaxAd, p1: MaxError) {
Log.d(TAG, "interstitial Ad MaX failed to show: ${p1.message}")
interstitialMaxAd = null
lastShowTime = System.currentTimeMillis()
failed?.invoke()
ReportAdUtils.showErrorAd(p1.message, INTERSTITIAL_AD_UNIT)
loadInterstitialAd(activity)
}
})
interstitialMaxAd?.showAd(activity)
}
}
fun showNativeAd(
activity: Activity,
completed: ((nativeAd: NativeAd) -> Unit)? = null,
maxCompleted: ((nativeAdLoader: MaxNativeAdLoader, nativeMaxAd: MaxAd) -> Unit)? = null,
failed: (() -> Unit?)? = null
) {
if (!isShowAdNative() || isBlacklist()) {
failed?.invoke()
return
}
Log.d(TAG, "native Ad load.")
ReportAdUtils.showPrepareAd(NATIVE_AD_UNIT)
if (useAdmob) {
var nativeAd: NativeAd? = null
val adLoader = AdLoader.Builder(activity, ConfigHelper.nativeAdmobId)
.forNativeAd { ad: NativeAd ->
completed?.invoke(ad)
ReportAdUtils.showAd(ad.responseInfo, NATIVE_AD_UNIT, activity)
ad.setOnPaidEventListener(ReportAdUtils.EventOnPaidEventListener(ad))
nativeAd = ad
}
.withAdListener(object : AdListener() {
override fun onAdClicked() {
Log.d(TAG, "native Ad clicked.")
ReportAdUtils.clickAd(nativeAd?.responseInfo, NATIVE_AD_UNIT)
}
override fun onAdFailedToLoad(loadAdError: LoadAdError) {
Log.d(TAG, "native Ad failed to load. ${loadAdError.message}")
failed?.invoke()
}
override fun onAdLoaded() {
Log.d(TAG, "native Ad loaded.")
}
})
.withNativeAdOptions(NativeAdOptions.Builder().build())
.build()
adLoader.loadAd(AdRequest.Builder().build())
} else {
val nativeAdLoader = MaxNativeAdLoader("", activity)
nativeAdLoader.setNativeAdListener(object : MaxNativeAdListener() {
override fun onNativeAdLoaded(nativeAdView: MaxNativeAdView?, ad: MaxAd) {
Log.d(TAG, "native Ad Max loaded.")
maxCompleted?.invoke(nativeAdLoader, ad)
}
override fun onNativeAdLoadFailed(adUnitId: String, error: MaxError) {
Log.d(TAG, "native Ad Max failed to load. ${error.message}")
failed?.invoke()
}
override fun onNativeAdClicked(ad: MaxAd) {
Log.d(TAG, "native Ad Max clicked.")
}
})
nativeAdLoader.loadAd()
}
}
fun showBannerAd(
context: Context,
adViewContainer: ViewGroup,
collapsible: String? = "bottom",
completed: (() -> Unit?)? = null,
failed: (() -> Unit?)? = null
) {
adViewContainer.viewTreeObserver.addOnGlobalLayoutListener(object :
ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
val screenPixelDensity = context.resources.displayMetrics.density
val adWidth = (adViewContainer.width / screenPixelDensity).toInt()
val adSize =
AdSize.getCurrentOrientationAnchoredAdaptiveBannerAdSize(context, adWidth)
showBannerAd(context, adViewContainer, adSize, collapsible, completed, failed)
adViewContainer.viewTreeObserver.removeOnGlobalLayoutListener(this)
}
})
}
fun showBannerAd(
context: Context,
adViewContainer: ViewGroup,
adSize: AdSize,
collapsible: String? = "bottom",
completed: (() -> Unit?)? = null,
failed: (() -> Unit?)? = null
) {
if (!isShowAdBanner() || isBlacklist()) {
failed?.invoke()
return
}
Log.d(TAG, "banner Ad load.")
val adView = AdView(context)
adView.adUnitId = ConfigHelper.bannerAdmobId
adView.setAdSize(adSize)
val extras = Bundle()
extras.putString("collapsible", collapsible)
val adRequest = AdRequest.Builder()
.addNetworkExtrasBundle(AdMobAdapter::class.java, extras)
.build()
adView.loadAd(adRequest)
adView.adListener = object : AdListener() {
override fun onAdClicked() {
Log.d(TAG, "banner Ad clicked.")
}
override fun onAdFailedToLoad(loadAdError: LoadAdError) {
Log.d(TAG, "banner Ad failed to load: ${loadAdError.message}")
failed?.invoke()
}
override fun onAdLoaded() {
Log.d(TAG, "banner Ad loaded.")
completed?.invoke()
}
}
adViewContainer.removeAllViews()
adViewContainer.addView(adView)
}
private fun showBannerAd(
context: Context,
adViewContainer: ViewGroup,
completed: (() -> Unit?)? = null,
failed: (() -> Unit?)? = null
) {
if (!isShowAdBanner() || isBlacklist()) {
failed?.invoke()
return
}
Log.d(TAG, "banner Ad Max load.")
val adView = MaxAdView("", context)
adView.setListener(object : MaxAdViewAdListener {
override fun onAdLoaded(p0: MaxAd) {
Log.d(TAG, "banner Ad Max loaded.")
completed?.invoke()
}
override fun onAdDisplayed(p0: MaxAd) {
}
override fun onAdHidden(p0: MaxAd) {
}
override fun onAdClicked(p0: MaxAd) {
Log.d(TAG, "banner Ad Max clicked.")
}
override fun onAdLoadFailed(p0: String, p1: MaxError) {
Log.d(TAG, "banner Ad Max failed to load: ${p1.message}")
failed?.invoke()
}
override fun onAdDisplayFailed(p0: MaxAd, p1: MaxError) {
}
override fun onAdExpanded(p0: MaxAd) {
}
override fun onAdCollapsed(p0: MaxAd) {
}
})
adViewContainer.removeAllViews()
adViewContainer.addView(adView)
adView.loadAd()
}
fun isShowAdBanner(): Boolean {
val isShowAdBanner = SpUtils.getInstance().getInt(KEY_IS_SHOW_AD_BANNER)
return isShowAdBanner == 1
}
fun isShowAdNative(): Boolean {
val isShowAdNative = SpUtils.getInstance().getInt(KEY_IS_SHOW_AD_NATIVE)
return isShowAdNative == 1
}
fun isShowAdInter(): Boolean {
val isShowAdInter = SpUtils.getInstance().getInt(KEY_IS_SHOW_AD_INTER, 1)
return isShowAdInter == 1
}
fun isShowAdBackInter(): Boolean {
val isShowAdBackInter = SpUtils.getInstance().getInt(KEY_IS_SHOW_AD_BACK_INTER)
return isShowAdBackInter == 1
}
fun isShowAdResultBackInter(): Boolean {
val isShowAdInter = SpUtils.getInstance().getInt(KEY_IS_SHOW_AD_RESULT_BACK_INTER)
return isShowAdInter == 1
}
fun isAppOpenAdAvailable(): Boolean {
return (if (useAdmob) appOpenAd != null else appOpenMaxAd?.isReady == true) && wasLoadTimeLessThanNHoursAgo(
1,
appOpenAdLoadTime
)
}
fun isInterstitialAdAvailable(): Boolean {
return (if (useAdmob) interstitialAd != null else interstitialMaxAd?.isReady == true) && wasLoadTimeLessThanNHoursAgo(
1,
interstitialAdLoadTime
)
}
private fun wasLoadTimeLessThanNHoursAgo(numHours: Long, time: Long): Boolean {
val dateDifference: Long = System.currentTimeMillis() - time
val numMilliSecondsPerHour: Long = 3600000
return dateDifference < numMilliSecondsPerHour * numHours
}
private fun isBlacklist(): Boolean {
return blacklist != 1
}
private fun checkAvailable(adUnit: String, checkIntervalTime: Boolean = false): Boolean {
if (isBlacklist()) {
ReportAdUtils.limitErrorAd(EVENT_BLACKLIST, adUnit)
return false
}
reset()
val displayNumber = SpUtils.getInstance().getInt(KEY_DISPLAY_NUMBER)
val requestNumber = SpUtils.getInstance().getInt(KEY_REQUEST_NUMBER)
val clickNumber = SpUtils.getInstance().getInt(KEY_CLICK_NUMBER)
val adShow = SpUtils.getInstance().getInt(KEY_AD_SHOW, DEFAULT_AD_SHOW)
val adRequest = SpUtils.getInstance().getInt(KEY_AD_REQUEST, DEFAULT_AD_REQUEST)
val adClick = SpUtils.getInstance().getInt(KEY_AD_CLICK, DEFAULT_AD_CLICK)
if (displayNumber >= adShow) {
ReportAdUtils.limitErrorAd(EVENT_SHOW_DISPLAYS, adUnit)
return false
}
if (requestNumber >= adRequest) {
ReportAdUtils.limitErrorAd(EVENT_SHOW_REQUESTS, adUnit)
return false
}
if (clickNumber >= adClick) {
ReportAdUtils.limitErrorAd(EVENT_SHOW_CLICKS, adUnit)
return false
}
if (!checkIntervalTime) return true
val interval = SpUtils.getInstance().getInt(KEY_AD_INTERVAL, DEFAULT_AD_INTERVAL) * 60 * 1000
val flag = System.currentTimeMillis() - lastShowTime > interval
if (!flag) {
ReportAdUtils.limitErrorAd(EVENT_SHOW_INTERVAL_TIME, adUnit)
}
return flag
}
fun Long.toFormatTime4(): String {
return SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH).format(this)
}
fun areTimestampsSameDay(timestamp1: Long, timestamp2: Long): Boolean {
val calendar1 = Calendar.getInstance().apply { timeInMillis = timestamp1 }
val calendar2 = Calendar.getInstance().apply { timeInMillis = timestamp2 }
// 比较年、月、日是否相同
return calendar1.get(Calendar.YEAR) == calendar2.get(Calendar.YEAR) &&
calendar1.get(Calendar.MONTH) == calendar2.get(Calendar.MONTH) &&
calendar1.get(Calendar.DAY_OF_MONTH) == calendar2.get(Calendar.DAY_OF_MONTH)
}
fun calculate(key: String) {
reset()
val value = SpUtils.getInstance().getInt(key)
SpUtils.getInstance().putInt(key, value + 1)
}
private fun reset() {
val currentTime = System.currentTimeMillis()
if (showTime.toInt() == 0 || showTime.toFormatTime4() != currentTime.toFormatTime4()) {
showTime = currentTime
SpUtils.getInstance().putInt(KEY_DISPLAY_NUMBER, 0)
SpUtils.getInstance().putInt(KEY_REQUEST_NUMBER, 0)
SpUtils.getInstance().putInt(KEY_CLICK_NUMBER, 0)
}
}
}
\ No newline at end of file
package com.base.pdfviewerscannerwhite.mix
import android.app.ActivityManager
import android.content.Context
import android.os.Environment
import android.os.StatFs
object AppHelps {
fun getMemTotal(context: Context): Long {
val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
val memoryInfo = ActivityManager.MemoryInfo()
activityManager.getMemoryInfo(memoryInfo)
return memoryInfo.totalMem
}
fun getMemAvailable(context: Context): Long {
val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
val memoryInfo = ActivityManager.MemoryInfo()
activityManager.getMemoryInfo(memoryInfo)
return memoryInfo.availMem
}
fun getTotalExternalSize(): Long {
try {
val statFs = StatFs(Environment.getExternalStorageDirectory().path)
val statFs2 = StatFs(Environment.getRootDirectory().path)
val blockSizeLong =
statFs2.blockSizeLong * statFs2.blockCountLong + statFs.blockSizeLong * statFs.blockCountLong
return calculateTotalExternal(blockSizeLong)
} catch (e: Exception) {
return 0
}
}
fun getAvailableExternalSize(): Long {
try {
val statFs = StatFs(Environment.getExternalStorageDirectory().path)
val statFs2 = StatFs(Environment.getRootDirectory().path)
val blackSize =
statFs2.blockSizeLong * statFs2.availableBlocksLong + statFs.blockSizeLong * statFs.availableBlocksLong
return calculateAvailableExternal(blackSize)
} catch (e: Exception) {
return 0
}
}
private fun calculateTotalExternal(size: Long): Long {
var powerOfTwo: Long = 1
while (powerOfTwo < size) {
powerOfTwo *= 2
}
return powerOfTwo
}
private fun calculateAvailableExternal(size: Long): Long {
var value = size
var n = 0
while (true) {
val m: Long = 1000
if (value < m) {
break
}
value /= m
n++
}
for (i in 0 until n) {
value *= 1024
}
return value
}
fun Context.dpToPx(dp: Int): Float {
val density = resources.displayMetrics.density
return dp * density
}
}
\ No newline at end of file
package com.base.pdfviewerscannerwhite.mix
import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.ValueAnimator
import android.app.Activity
import android.app.Dialog
import android.content.Intent
import android.os.Bundle
import android.view.View
import android.view.animation.LinearInterpolator
import androidx.appcompat.app.AppCompatActivity
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.lifecycle.lifecycleScope
import com.airbnb.lottie.LottieAnimationView
import com.base.pdfviewerscannerwhite.R
import com.base.pdfviewerscannerwhite.ads.AdmobHelper
import com.base.pdfviewerscannerwhite.ads.admob.AdmobInterstitialUtils
import com.base.pdfviewerscannerwhite.helper.EventUtils
import com.base.pdfviewerscannerwhite.mix.DialogHelps.showExitDialog
import com.base.pdfviewerscannerwhite.ui.appprocess.AppProcessActivity
import com.base.pdfviewerscannerwhite.ui.main.MainActivity
import com.base.pdfviewerscannerwhite.utils.ActivityLauncher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlin.random.Random
open class BaseActivity2 : AppCompatActivity() {
protected lateinit var launcher: ActivityLauncher
protected var loadingDialog: Dialog? = null
protected var isDisableBack = false
private var isShowAdInterstitial = false
private var isPause = false
private var lottieType: LottieType? = null
private var complete: (() -> Unit?)? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
launcher = ActivityLauncher(this)
immersive()
ActivityManagerHelps.add(this)
EventUtils.event("${javaClass.simpleName}_show")
}
override fun onResume() {
super.onResume()
isPause = false
}
override fun onPause() {
super.onPause()
isPause = true
}
override fun onDestroy() {
super.onDestroy()
ActivityManagerHelps.remove(this)
lottieType = null
complete = null
}
protected open fun immersive() {
StatusBarHelps.immersive(this, getColor(R.color.color_8eb0ff))
}
protected fun showAnimationAd(
lottieType: LottieType = LottieType.CLEAN,
isShowAnimation: Boolean = true,
complete: (() -> Unit?)? = null
) {
this.lottieType = lottieType
this.complete = complete
AdmobInterstitialUtils.showInterstitialAd(this, false, false) {
// showAdInterstitial(true) {
val animationView = findViewById<ConstraintLayout>(R.id.animation)
animationView.setOnClickListener { }
if (isShowAnimation) {
StatusBarHelps.immersive(this, getColor(R.color.color_8eb0ff))
showAnimation(animationView, lottieType, complete)
} else {
complete?.invoke()
}
}
}
protected fun showAdInterstitial(isShow: Boolean, complete: (() -> Unit?)? = null) {
if (this.isFinishing || this.isDestroyed || isShowAdInterstitial) return
isShowAdInterstitial = true
if (isShow) {
AdmobHelps.showInterstitialAd(
this,
dismissed = {
clearLoading()
immersive()
complete?.invoke()
},
completed = {
StatusBarHelps.immersive(this, getColor(R.color.black))
loadingDialog?.dismiss()
},
failed = {
clearLoading()
immersive()
complete?.invoke()
}
)
} else {
isShowAdInterstitial = false
complete?.invoke()
}
}
protected fun showAnimation(
view: View,
lottieType: LottieType,
complete: (() -> Unit?)? = null
) {
isDisableBack = true
view.visibility = View.VISIBLE
val progress = view.findViewById<androidx.appcompat.widget.AppCompatTextView>(R.id.tv_progress)
progress.text = "0%"
val lottie = view.findViewById<LottieAnimationView>(R.id.lottie_animation)
lottie.setAnimation(lottieType.data)
lottie.loop(isLoop(lottieType))
lottie.playAnimation()
if (!lottieType.images.isNullOrEmpty())
lottie.imageAssetsFolder = lottieType.images
if (!isLoop(lottieType)) {
lottie.addAnimatorUpdateListener { animation ->
val value = animation.animatedValue as Float * 100
progress.text = "${value.toInt()}%"
if (value.toInt() == 100) {
view.visibility = View.GONE
complete?.invoke()
isDisableBack = false
}
}
return
}
lifecycleScope.launch(Dispatchers.Main) {
val durationTime = Random.Default.nextLong(3000, 3500)
ValueAnimator.ofInt(0, 100).apply {
duration = durationTime
interpolator = LinearInterpolator()
addUpdateListener { animation ->
val value = animation.animatedValue as Int
progress.text = "${value}%"
}
addListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
view.visibility = View.GONE
complete?.invoke()
isDisableBack = false
lottie.cancelAnimation()
}
})
}.start()
}
}
private fun isLoop(lottieType: LottieType): Boolean {
return lottieType != LottieType.CLEAN
}
private fun clearLoading() {
loadingDialog?.dismiss()
loadingDialog = null
isShowAdInterstitial = false
}
protected fun cleanFiles(list: List<FileBean>) {
lifecycleScope.launch(Dispatchers.IO) {
val paths = list.filter { it.isSelected }.map { it.path }.toTypedArray()
paths.forEach { FileHelps.deleteFile(it) }
withContext(Dispatchers.Main) {
MediaHelps.updateMedia(applicationContext, paths)
}
}
}
protected fun backPressed() {
onBackPressedDispatcher.onBackPressed()
}
fun handleBackPressed(activity: Activity) {
when (activity) {
// is CleanJunkActivity -> exit(ExitType.CLEAN)
// is SimilarPhotosActivity -> exit(ExitType.SIMILAR_PHOTOS)
is ScreenshotCleanActivity -> exit(ExitType.SCREENSHOT)
// is WhatsappCleanActivity -> exit(ExitType.WHATSAPP)
// is WhatsappCleanDetailActivity -> exit(ExitType.WHATSAPP)
is AppProcessActivity -> exit(ExitType.APP_PROCESS)
else -> finishToMainTop()
}
}
private fun exit(exit: ExitType) {
showExitDialog(this, getString(exit.title), getString(exit.content)) {
backAdJump()
}
}
fun backAdJump() {
if (AdmobHelper.isShowCloseDocumentInter()) {
showAdInterstitial(true) {
finishToMainTop()
}
} else {
finishToMainTop()
}
}
fun finishToMainTop() {
val intent = Intent(this, MainActivity::class.java)
intent.putExtra("where", "finishToMainTop")
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
startActivity(intent)
finish()
}
}
\ No newline at end of file
package com.base.pdfviewerscannerwhite.mix
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import androidx.viewbinding.ViewBinding
abstract class BaseAdapter<T, VB : ViewBinding>(
private var items: List<T> = emptyList()
) : RecyclerView.Adapter<BaseViewHolder<VB>>() {
interface OnClickCallback<T> {
fun onClicked(view: View, position: Int, item: T)
}
var callback: OnClickCallback<T>? = null
fun submitList(data: List<T>) {
items = data
notifyDataSetChanged()
}
fun add(item: T) {
items = items.toMutableList().apply { add(item) }
notifyItemInserted(items.size - 1)
}
val list: MutableList<T> get() = items.toMutableList()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder<VB> {
return BaseViewHolder(getViewBinding(LayoutInflater.from(parent.context), parent))
}
override fun onBindViewHolder(holder: BaseViewHolder<VB>, position: Int) {
bind(holder, position, items[position])
}
override fun getItemCount(): Int = items.size
abstract fun getViewBinding(layoutInflater: LayoutInflater, parent: ViewGroup): VB
abstract fun bind(holder: BaseViewHolder<VB>, position: Int, item: T)
}
\ No newline at end of file
package com.base.pdfviewerscannerwhite.mix
import androidx.recyclerview.widget.RecyclerView
import androidx.viewbinding.ViewBinding
class BaseViewHolder<VB : ViewBinding>(val binding: VB) : RecyclerView.ViewHolder(binding.root)
\ No newline at end of file
package com.base.pdfviewerscannerwhite.mix
import android.media.tv.TvTrackInfo.TYPE_AUDIO
import android.media.tv.TvTrackInfo.TYPE_VIDEO
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import com.base.pdfviewerscannerwhite.R
import com.base.pdfviewerscannerwhite.databinding.ItemCleanDetailBinding
import com.base.pdfviewerscannerwhite.mix.AppHelps.dpToPx
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.bitmap.CenterCrop
import com.bumptech.glide.request.RequestOptions
class CleanDetailAdapter(
var data: List<FileBean>,
private val type: Int = TYPE_VIDEO
) : BaseAdapter<FileBean, ItemCleanDetailBinding>(data) {
constructor(type: Int = TYPE_VIDEO) : this(emptyList(), type)
override fun getViewBinding(
layoutInflater: LayoutInflater,
parent: ViewGroup
): ItemCleanDetailBinding {
return ItemCleanDetailBinding.inflate(layoutInflater, parent, false)
}
override fun bind(
holder: BaseViewHolder<ItemCleanDetailBinding>,
position: Int,
item: FileBean
) {
if (type == TYPE_AUDIO) {
holder.binding.clVideoImage.visibility = View.GONE
holder.binding.clAudio.visibility = View.VISIBLE
holder.itemView.layoutParams =
ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
holder.binding.tvAudioName.text = item.name
holder.binding.tvAudioSize.text = Utils.getSize(item.length)
setSelection(holder.binding.ivAudioSelect, item)
holder.binding.viewLine.visibility = if (position == itemCount - 1) View.GONE else View.VISIBLE
holder.itemView.setOnClickListener {
item.isSelected = !item.isSelected
setSelection(holder.binding.ivAudioSelect, item)
callback?.onClicked(it, position, item)
}
} else {
holder.binding.clVideoImage.visibility = View.VISIBLE
holder.binding.clAudio.visibility = View.GONE
holder.binding.ivVideo.visibility = if (type == TYPE_VIDEO) View.VISIBLE else View.GONE
holder.itemView.layoutParams =
ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
val width = holder.itemView.context.resources.displayMetrics.widthPixels
val margin = holder.itemView.context.dpToPx(44).toInt()
val imageWidth = (width - margin) / 3
holder.binding.ivImage.layoutParams.width = imageWidth
holder.binding.ivImage.layoutParams.height = imageWidth
val round = holder.itemView.context.dpToPx(8).toInt()
val options = RequestOptions().transform(CenterCrop(), RoundedCorners(round))
Glide.with(holder.itemView.context)
.load(item.path)
.apply(options)
.into(holder.binding.ivImage)
holder.binding.tvSize.text = Utils.getSize(item.length)
holder.binding.ivVideo.visibility = if (type == 0) View.VISIBLE else View.GONE
setSelection(holder.binding.ivSelect, item)
holder.itemView.setOnClickListener {
item.isSelected = !item.isSelected
setSelection(holder.binding.ivSelect, item)
callback?.onClicked(it, position, item)
}
}
}
private fun setSelection(imageView: ImageView, item: FileBean) {
imageView.setImageResource(if (item.isSelected) R.mipmap.ic_check_s else R.mipmap.ic_check_n)
}
}
\ No newline at end of file
package com.base.pdfviewerscannerwhite.mix
import android.animation.ObjectAnimator
import android.app.Activity
import android.app.Dialog
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.animation.LinearInterpolator
import com.base.pdfviewerscannerwhite.R
import com.base.pdfviewerscannerwhite.databinding.DialogDeleteBinding
import com.base.pdfviewerscannerwhite.databinding.DialogDeleteMixBinding
import com.base.pdfviewerscannerwhite.databinding.DialogExitBinding
import com.base.pdfviewerscannerwhite.databinding.DialogStoragePermissionBinding
import com.google.android.material.bottomsheet.BottomSheetDialog
object DialogHelps {
fun showStoragePermissionDialog(context: Context, open: () -> Unit, dismiss: () -> Unit) {
val binding = DialogStoragePermissionBinding.inflate(LayoutInflater.from(context))
val dialog = BottomSheetDialog(context, R.style.BottomSheetDialog).apply {
setContentView(binding.root)
show()
}
dialog.setOnDismissListener { dismiss.invoke() }
binding.tvSet.setOnClickListener {
it.isEnabled = false
open.invoke()
it.postDelayed({ dialog.dismiss() }, 500)
}
}
private fun scoreAnimation(view: View) {
ObjectAnimator.ofFloat(
view,
View.SCALE_X,
0.75f,
1.2f,
1f
).apply {
duration = 500
interpolator = LinearInterpolator()
start()
}
ObjectAnimator.ofFloat(
view,
View.SCALE_Y,
0.75f,
1.2f,
1f
).apply {
duration = 500
interpolator = LinearInterpolator()
start()
}
}
fun showDeleteDialog(context: Context, view: View, confirm: (() -> Unit?)?): DialogDeleteMixBinding {
view.isEnabled = false
val binding = DialogDeleteMixBinding.inflate(LayoutInflater.from(context))
val dialog = Dialog(context, R.style.CustomDialogStyle).apply {
setCancelable(false)
setCanceledOnTouchOutside(false)
setContentView(binding.root)
show()
}
binding.tvCancel.setOnClickListener {
dialog.dismiss()
view.isEnabled = true
}
binding.tvDelete.setOnClickListener {
it.isEnabled = false
dialog.dismiss()
confirm?.invoke()
view.isEnabled = true
}
return binding
}
fun showExitDialog(
context: Activity,
title: String,
content: Any,
confirm: () -> Unit,
) {
val binding = DialogExitBinding.inflate(LayoutInflater.from(context))
val dialog = Dialog(context, R.style.CustomDialogStyle).apply {
setCancelable(false)
setCanceledOnTouchOutside(false)
setContentView(binding.root)
show()
}
binding.tvTitle.text = title
binding.tvContent.text = content.toString()
binding.ivCancel.setOnClickListener {
dialog.dismiss()
}
binding.tvCancel.setOnClickListener {
dialog.dismiss()
}
binding.tvSure.setOnClickListener {
it.isEnabled = false
dialog.dismiss()
confirm.invoke()
}
AdmobHelps.showNativeAd(context, completed = {
binding.adNative.setExitNativeAd(it)
}, maxCompleted = { nativeAdLoader, nativeMaxAd ->
binding.adNative.setExitNativeAd(nativeAdLoader, nativeMaxAd)
})
}
}
\ No newline at end of file
package com.base.pdfviewerscannerwhite.mix
import com.base.pdfviewerscannerwhite.R
enum class ExitType(val title: Int, val content: Int) {
APP_PROCESS(R.string.exit_app_process, R.string.exit_app_process_content1),
SCREENSHOT(R.string.exit_screenshot_cleaner, R.string.exit_screenshot_cleaner_content),
SIMILAR_PHOTOS(R.string.exit_similar_photos, R.string.exit_similar_photos_content),
WHATSAPP(R.string.exit_whatsapp_clean, R.string.exit_whatsapp_clean_content),
CLEAN(R.string.exit_clean_junk, R.string.exit_clean_junk_content),
}
\ No newline at end of file
package com.base.pdfviewerscannerwhite.mix
data class FileBean(
val name: String,
val path: String = "",
var icon: Int = 0,
var length: Long = 0,
var lastModified: Long = 0,
var mineType: String = "",
var isSelected: Boolean = false,
var isScanning: Boolean = true,
var state: Int = 0,
var type: Int = 0,
var items: List<FileBean> = emptyList()
)
package com.base.pdfviewerscannerwhite.mix
import android.os.Environment
import androidx.lifecycle.LifecycleCoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.joinAll
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
object FileHelps {
private const val WHATS_APP_MEDIA_DIR = "Android/media/com.whatsapp/WhatsApp/Media/"
fun findWhatsappFiles(): MutableList<FileBean> {
val rootDir = File(getAppSpecificDirPath(WHATS_APP_MEDIA_DIR))
// val rootDir = File(getAppSpecificDirPath("Pictures/"))
val list = findFilesRecursive(rootDir, arrayOf())
list.sortByDescending { it.lastModified }
return list
}
suspend fun findEmptyFolders(lifecycleScope: LifecycleCoroutineScope): MutableList<FileBean> {
val rootDir = Environment.getExternalStorageDirectory()
val filters = arrayOf("/storage/emulated/0/Android/data", "/storage/emulated/0/Android/obb")
val emptyFolders = mutableListOf<File>()
// 使用协程并发遍历文件夹
withContext(Dispatchers.IO) {
findEmptyFolders(lifecycleScope, rootDir, filters, emptyFolders)
}
return emptyFolders.map { FileBean(it.name ?: "null", it.path, length = 4 * 1024) }.toMutableList()
}
private suspend fun findEmptyFolders(
lifecycleScope: LifecycleCoroutineScope,
folder: File,
filters: Array<String>,
emptyFolders: MutableList<File>
) {
val files = folder.listFiles() ?: return
if (files.isEmpty() && !filters.contains(folder.path)) {
emptyFolders.add(folder)
return
}
files.filter { it.isDirectory }.map { file ->
lifecycleScope.launch(Dispatchers.IO) {
findEmptyFolders(lifecycleScope, file, filters, emptyFolders)
}
}.joinAll() // 等待所有子任务完成
}
// fun findEmptyFolders(): MutableList<FileBean> {
// val externalStorageDir = Environment.getExternalStorageDirectory()
// val filters = arrayOf("/storage/emulated/0/Android/data", "/storage/emulated/0/Android/obb")
// val emptyFolders = getAllEmptyFolders(externalStorageDir, filters)
// return emptyFolders.map { FileBean(it.name, it.path, length = 4 * 1024) }.toMutableList()
// }
fun findTempFiles(): MutableList<FileBean> {
val rootDir = Environment.getExternalStorageDirectory()
return findFilesRecursive(rootDir, arrayOf(".temp"))
}
fun findApkFiles(): MutableList<FileBean> {
val rootDir = Environment.getExternalStorageDirectory()
return findFilesRecursive(rootDir, arrayOf(".apk", ".aab"))
}
fun findLogFiles(): MutableList<FileBean> {
val rootDir = Environment.getExternalStorageDirectory()
return findFilesRecursive(rootDir, arrayOf(".log"))
}
fun deleteFile(filePath: String) {
File(filePath).deleteIfExists()
}
fun File?.deleteIfExists(): Boolean {
if (this?.exists() == true) {
return this.delete()
}
return false
}
private fun findFilesRecursive(dir: File, suffixes: Array<String>): MutableList<FileBean> {
return dir.walk()
.filter { it.isFile && it.endsWith(suffixes) }
.map { FileBean(it.name, it.path, length = it.length(), lastModified = it.lastModified()) }
.toMutableList()
}
private fun File.endsWith(suffixes: Array<String>): Boolean {
return suffixes.isEmpty() || suffixes.any { name.lowercase().endsWith(it.lowercase()) }
}
private fun getAppSpecificDirPath(relativePath: String): String {
return "${Environment.getExternalStorageDirectory()}/$relativePath"
}
private fun getAllEmptyFolders(root: File, filters: Array<String>): List<File> {
return root.walk()
.filter {
it.isDirectory && !filters.contains(it.path) && !it.isHidden && it.list()?.isEmpty() == true
}
.toList()
}
}
\ No newline at end of file
package com.base.pdfviewerscannerwhite.mix
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Color
import android.media.ThumbnailUtils
import com.base.pdfviewerscannerwhite.bean.SimilarBean
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.File
import kotlin.math.pow
object ImageHelpers {
private fun loadBitmapFromFile(path: String): Bitmap? {
val bitmap = BitmapFactory.decodeFile(path)
if (bitmap.width <= 0 || bitmap.height <= 0) {
return null
}
val options = BitmapFactory.Options()
options.inJustDecodeBounds = true
BitmapFactory.decodeFile(path, options)
if (options.outHeight == -1 || options.outWidth == -1) {
return null
}
var inSampleSize =
(0.5f + options.outHeight.toFloat() / bitmap.height.toFloat()).coerceAtLeast(0.5f + options.outWidth.toFloat() / bitmap.width.toFloat())
.toInt()
inSampleSize += 1
options.inSampleSize = inSampleSize.coerceAtLeast(1)
options.inJustDecodeBounds = false
return BitmapFactory.decodeFile(path, options)
}
suspend fun createImage(path: String): SimilarBean? {
return withContext(Dispatchers.IO) {
try {
val width = 8
val height = 8
val source = loadBitmapFromFile(path)
val thumb = ThumbnailUtils.extractThumbnail(source, width, height)
val pixels = IntArray(width * height)
for (i in 0 until width) {
for (j in 0 until height) {
pixels[i * height + j] = rgbToGray(thumb.getPixel(i, j))
}
}
val avgPixel = average(pixels)
val comps = IntArray(width * height)
for (i in comps.indices) {
if (pixels[i] >= avgPixel) {
comps[i] = 1
} else {
comps[i] = 0
}
}
val hashCode = StringBuffer()
var i = 0
while (i < comps.size) {
val result = comps[i] * 2.0.pow(3.0).toInt() + (comps[i + 1] * 2.0.pow(2.0)
.toInt()) + (comps[i + 2] * 2.0.pow(1.0).toInt()) + comps[i + 3]
hashCode.append(binaryToHex(result))
i += 4
}
recycleBitmap(thumb)
recycleBitmap(source)
return@withContext SimilarBean(
path,
hashCode.toString(),
avgPixel,
File(path).length(),
false
)
} catch (_: Exception) {
return@withContext null
}
}
}
private fun rgbToGray(pixels: Int): Int {
val red = Color.red(pixels)
val green = Color.green(pixels)
val blue = Color.blue(pixels)
return (0.3 * red + 0.59 * green + 0.11 * blue).toInt()
}
private fun average(pixels: IntArray): Int {
return (pixels.sumOf { it }.toFloat() / pixels.size).toInt()
}
private fun recycleBitmap(thumb: Bitmap?) {
if (thumb?.isRecycled == false) {
thumb.recycle()
}
}
fun similarCondition(first: SimilarBean, second: SimilarBean): Boolean {
return hammingDistance(
first.hashCode,
second.hashCode
) <= 6 && (first.avgPixel.toFloat() / second.avgPixel) in 0.8..1.0
}
private fun hammingDistance(sourceHashCode: String, hashCode: String): Int {
var difference = 0
for (i in sourceHashCode.indices) {
if (sourceHashCode[i] != hashCode[i]) {
difference++
}
}
return difference
}
private fun binaryToHex(binary: Int) = when (binary) {
0 -> '0'
1 -> '1'
2 -> '2'
3 -> '3'
4 -> '4'
5 -> '5'
6 -> '6'
7 -> '7'
8 -> '8'
9 -> '9'
10 -> 'a'
11 -> 'b'
12 -> 'c'
13 -> 'd'
14 -> 'e'
15 -> 'f'
else -> ' '
}
}
\ No newline at end of file
package com.base.pdfviewerscannerwhite.mix
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.View
import androidx.appcompat.widget.AppCompatImageView
import androidx.appcompat.widget.AppCompatTextView
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import com.base.pdfviewerscannerwhite.R
import com.base.pdfviewerscannerwhite.databinding.ActivityLargeFileCleanBinding
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.util.Calendar
class LargeFileCleanActivity : BaseActivity2() {
companion object {
fun start(context: Context) {
val intent = Intent(context, LargeFileCleanActivity::class.java)
context.startActivity(intent)
}
}
private val binding by lazy {
ActivityLargeFileCleanBinding.inflate(layoutInflater)
}
private val LARGE_FILE_SIZE: Long = 1024 * 1024 * 10
private val typeList by lazy {
listOf(
FileBean(getString(R.string.all_types), isSelected = true),
FileBean(getString(R.string.image)),
FileBean(getString(R.string.video)),
FileBean(getString(R.string.audio)),
FileBean(getString(R.string.document)),
FileBean(getString(R.string.apk)),
FileBean(getString(R.string.other_types)),
)
}
private val sizeList by lazy {
listOf(
FileBean(getString(R.string.mb_10), isSelected = true),
FileBean(getString(R.string.mb_20)),
FileBean(getString(R.string.mb_50)),
FileBean(getString(R.string.mb_100)),
FileBean(getString(R.string.mb_500)),
)
}
private val timeList by lazy {
listOf(
FileBean(getString(R.string.all_time), isSelected = true),
FileBean(getString(R.string.week_1)),
FileBean(getString(R.string.month_1)),
FileBean(getString(R.string.month_3)),
FileBean(getString(R.string.month_6)),
FileBean(getString(R.string.year_1)),
)
}
private lateinit var adapter: LargeFileCleanAdapter
private lateinit var tabAdapter: LargeFileCleanTabAdapter
private var files = listOf<FileBean>()
private var typePosition = 0
private var sizePosition = 0
private var timePosition = 0
private var total: Long = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
initView()
initData()
showAnimationAd(LottieType.LARGE_FILE)
AdmobHelps.showNativeAd(this, completed = {
binding.adNative.setNativeAd(it)
}, maxCompleted = { nativeAdLoader, nativeMaxAd ->
binding.adNative.setNativeAd(nativeAdLoader, nativeMaxAd)
})
}
private fun initView() {
adapter = LargeFileCleanAdapter()
adapter.callback = object : BaseAdapter.OnClickCallback<FileBean> {
override fun onClicked(view: View, position: Int, item: FileBean) {
total = adapter.list.filter { it.isSelected }.sumOf { it.length }
val delete = getString(R.string.delete)
val size = if (total > 0) "(${Utils.getSize(total)})" else ""
binding.tvDelete.text = "${delete} ${size}"
binding.tvDelete.setBackgroundResource(if (total > 0) R.drawable.gradient_37 else R.drawable.gradient_not_clickable)
}
}
binding.rvLargeFile.adapter = adapter
binding.rvLargeFile.layoutManager = LinearLayoutManager(this)
tabAdapter = LargeFileCleanTabAdapter()
tabAdapter.callback = object : BaseAdapter.OnClickCallback<FileBean> {
override fun onClicked(view: View, position: Int, item: FileBean) {
binding.clTab.visibility = View.GONE
var textView: AppCompatTextView = binding.tvTime
when (tabAdapter.type) {
1 -> {
textView = binding.tvType
typePosition = position
}
2 -> {
textView = binding.tvSize
sizePosition = position
}
3 -> {
textView = binding.tvTime
timePosition = position
}
}
textView.text = item.name
binding.tvDelete.text = getString(R.string.delete)
filterData()
clearTab()
}
}
binding.rvTab.adapter = tabAdapter
binding.rvTab.layoutManager = LinearLayoutManager(this)
binding.flBack.setOnClickListener { backPressed() }
binding.llType.setOnClickListener {
setTab(it, binding.tvType, binding.ivTypeArrow)
}
binding.llSize.setOnClickListener {
setTab(it, binding.tvSize, binding.ivSizeArrow)
}
binding.llTime.setOnClickListener {
setTab(it, binding.tvTime, binding.ivTimeArrow)
}
binding.clTab.setOnClickListener {
hiddenTab()
}
binding.tvDelete.setOnClickListener {
if (total <= 0) return@setOnClickListener
DialogHelps.showDeleteDialog(this, binding.tvDelete) {
cleanFiles(adapter.list)
showAnimationAd {
// toCleanResult(total, getString(R.string.large_file_clean))
}
}
}
}
private fun initData() {
lifecycleScope.launch(Dispatchers.IO) {
files = async { MediaHelps.findFiles(this@LargeFileCleanActivity, LARGE_FILE_SIZE) }.await()
withContext(Dispatchers.Main) {
binding.tvDelete.visibility = if (files.isEmpty()) View.GONE else View.VISIBLE
filterData()
}
}
}
private fun showEmpty(isShow: Boolean) {
binding.rvLargeFile.visibility = if (isShow) View.GONE else View.VISIBLE
binding.ivEmpty.visibility = if (isShow) View.VISIBLE else View.GONE
}
private fun hiddenTab() {
binding.clTab.visibility = View.GONE
binding.llType.isSelected = false
binding.llSize.isSelected = false
binding.llTime.isSelected = false
clearTab()
}
private fun setTab(
view: View,
textView: AppCompatTextView,
imageView: AppCompatImageView
) {
if (view.isSelected) {
hiddenTab()
return
}
clearTab()
view.isSelected = true
view.setBackgroundResource(R.drawable.gradient_37)
imageView.setImageResource(R.mipmap.icon_jiantou_up_small)
textView.setTextColor(getColor(R.color.white))
binding.llTab.setBackgroundResource(R.color.white)
when (view) {
binding.llType -> {
binding.ivType.setImageResource(R.mipmap.icon_all_s)
binding.tvOtherThan.visibility = View.GONE
showTab(1, typeList)
}
binding.llSize -> {
binding.ivSize.setImageResource(R.mipmap.icon_mb_s)
binding.tvOtherThan.text = getString(R.string.larger_than)
binding.tvOtherThan.visibility = View.VISIBLE
showTab(2, sizeList)
}
binding.llTime -> {
binding.ivTime.setImageResource(R.mipmap.icon_time_s)
binding.tvOtherThan.text = getString(R.string.other_types)
binding.tvOtherThan.visibility = View.VISIBLE
showTab(3, timeList)
}
}
}
private fun clearTab() {
binding.llTab.setBackgroundResource(R.color.color_f7fafa)
binding.tvDelete.setBackgroundResource(R.drawable.gradient_not_clickable)
binding.llType.setBackgroundResource(R.drawable.large_file_tab)
binding.llSize.setBackgroundResource(R.drawable.large_file_tab)
binding.llTime.setBackgroundResource(R.drawable.large_file_tab)
binding.ivType.setImageResource(R.mipmap.icon_all_n)
binding.ivSize.setImageResource(R.mipmap.icon_mb_n)
binding.ivTime.setImageResource(R.mipmap.icon_time_n)
binding.tvType.setTextColor(getColor(R.color.color_181b1f))
binding.tvSize.setTextColor(getColor(R.color.color_181b1f))
binding.tvTime.setTextColor(getColor(R.color.color_181b1f))
binding.ivTypeArrow.setImageResource(R.mipmap.icon_jiantou_down_small)
binding.ivSizeArrow.setImageResource(R.mipmap.icon_jiantou_down_small)
binding.ivTimeArrow.setImageResource(R.mipmap.icon_jiantou_down_small)
binding.llType.isSelected = false
binding.llSize.isSelected = false
binding.llTime.isSelected = false
}
private fun showTab(type: Int, list: List<FileBean>) {
binding.clTab.visibility = View.VISIBLE
tabAdapter.type = type
tabAdapter.submitList(list)
}
private fun filterData() {
files.forEach { it.isSelected = false }
var list = filterType(files, typePosition)
list = filterSize(list, sizePosition)
list = filterTime(list, timePosition)
adapter.submitList(list)
showEmpty(list.isEmpty())
binding.tvDelete.visibility = if (list.isEmpty()) View.GONE else View.VISIBLE
}
private fun filterType(list: List<FileBean>, position: Int): List<FileBean> {
return when (position) {
1 -> list.filter { MineTypeHelps.isImage(it.mineType) }
2 -> list.filter { MineTypeHelps.isVideo(it.mineType) }
3 -> list.filter { MineTypeHelps.isAudio(it.mineType) }
4 -> list.filter { MineTypeHelps.isDoc(it.mineType) }
5 -> list.filter { MineTypeHelps.isApk(it.mineType) }
6 -> list.filterNot { file ->
MineTypeHelps.mineTypes.any { mimeType -> file.mineType.startsWith(mimeType) }
}
else -> {
list
}
}
}
private fun filterSize(list: List<FileBean>, position: Int): List<FileBean> {
return when (position) {
1 -> list.filter { it.length >= LARGE_FILE_SIZE * 2 }
2 -> list.filter { it.length >= LARGE_FILE_SIZE * 5 }
3 -> list.filter { it.length >= LARGE_FILE_SIZE * 10 }
4 -> list.filter { it.length >= LARGE_FILE_SIZE * 50 }
else -> {
list.filter { it.length >= LARGE_FILE_SIZE }
}
}
}
private fun filterTime(list: List<FileBean>, position: Int): List<FileBean> {
return when (position) {
1 -> list.filter { it.lastModified > Calendar.getInstance().apply { add(Calendar.WEEK_OF_YEAR, -1) }.timeInMillis }
2 -> list.filter { it.lastModified > Calendar.getInstance().apply { add(Calendar.MONTH, -1) }.timeInMillis }
3 -> list.filter { it.lastModified > Calendar.getInstance().apply { add(Calendar.MONTH, -3) }.timeInMillis }
4 -> list.filter { it.lastModified > Calendar.getInstance().apply { add(Calendar.MONTH, -6) }.timeInMillis }
5 -> list.filter { it.lastModified > Calendar.getInstance().apply { add(Calendar.YEAR, -1) }.timeInMillis }
else -> {
list
}
}
}
}
\ No newline at end of file
package com.base.pdfviewerscannerwhite.mix
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.isVisible
import com.base.pdfviewerscannerwhite.R
import com.base.pdfviewerscannerwhite.databinding.ItemLargeFileCleanBinding
import com.base.pdfviewerscannerwhite.mix.AppHelps.dpToPx
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.bitmap.CenterCrop
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
import com.bumptech.glide.request.RequestOptions
class LargeFileCleanAdapter : BaseAdapter<FileBean, ItemLargeFileCleanBinding>() {
override fun getViewBinding(
layoutInflater: LayoutInflater,
parent: ViewGroup
): ItemLargeFileCleanBinding {
return ItemLargeFileCleanBinding.inflate(layoutInflater, parent, false)
}
override fun bind(
holder: BaseViewHolder<ItemLargeFileCleanBinding>,
position: Int,
item: FileBean
) {
holder.binding.ivVideo.isVisible = MineTypeHelps.isVideo(item.mineType)
if (MineTypeHelps.isImage(item.mineType) || MineTypeHelps.isVideo(item.mineType)) {
showImageVideo(holder, item)
} else if (MineTypeHelps.isAudio(item.mineType)) {
holder.binding.ivIcon.setImageResource(R.mipmap.icon1)
} else if (MineTypeHelps.isApk(item.mineType)) {
holder.binding.ivIcon.setImageResource(R.mipmap.icon3)
} else if (MineTypeHelps.isDoc(item.mineType)) {
holder.binding.ivIcon.setImageResource(R.mipmap.icon4)
} else {
holder.binding.ivIcon.setImageResource(R.mipmap.icon2)
}
holder.binding.tvName.text = item.name
holder.binding.tvLength.text = Utils.getSize(item.length)
holder.binding.ivSelect.setImageResource(if (item.isSelected) R.mipmap.icon_yuan_junk_s else R.mipmap.icon_all_photo_off)
holder.binding.viewLine.visibility = if (position == itemCount - 1) View.GONE else View.VISIBLE
holder.itemView.setOnClickListener {
item.isSelected = !item.isSelected
notifyItemChanged(position)
callback?.onClicked(it, position, item)
}
}
private fun showImageVideo(
holder: BaseViewHolder<ItemLargeFileCleanBinding>,
item: FileBean
) {
val round = holder.itemView.context.dpToPx(4).toInt()
val options = RequestOptions().transform(CenterCrop(), RoundedCorners(round))
Glide.with(holder.itemView.context)
.load(item.path)
.apply(options)
.into(holder.binding.ivIcon)
}
}
\ No newline at end of file
package com.base.pdfviewerscannerwhite.mix
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.base.pdfviewerscannerwhite.databinding.ItemLargeFileCleanTabBinding
import com.base.pdfviewerscannerwhite.R
class LargeFileCleanTabAdapter : BaseAdapter<FileBean, ItemLargeFileCleanTabBinding>() {
var type = 0
override fun getViewBinding(
layoutInflater: LayoutInflater,
parent: ViewGroup
): ItemLargeFileCleanTabBinding {
return ItemLargeFileCleanTabBinding.inflate(layoutInflater, parent, false)
}
override fun bind(
holder: BaseViewHolder<ItemLargeFileCleanTabBinding>,
position: Int,
item: FileBean
) {
holder.binding.tvName.text = item.name
holder.binding.ivSelect.setImageResource(if (item.isSelected) R.mipmap.icon_yuan_junk_s else R.mipmap.icon_all_photo_off)
holder.binding.viewLine.visibility = if (position == itemCount - 1) View.GONE else View.VISIBLE
holder.itemView.setOnClickListener {
list.forEach { it.isSelected = false }
item.isSelected = !item.isSelected
callback?.onClicked(it, position, item)
}
}
}
\ No newline at end of file
package com.base.pdfviewerscannerwhite.mix
enum class LottieType(val data: String, val images: String? = null) {
APP_MANAGER("app_manager/scan/data.json", "app_manager/scan/images"),
APP_PROCESS("app_process/scan/data.json", "app_process/scan/images"),
BATTERY_INFO("battery_info/scan/data.json", "battery_info/scan/images"),
LARGE_FILE("large_files/scan/data.json", "large_files/scan/images"),
PHOTO_COMPRESSION("photo_compression/scan/data.json", "photo_compression/scan/images"),
PHOTO_COMPRESSION_COMPRESS("photo_compression/compress/data.json", "photo_compression/compress/images"),
SCREENSHOT("screenshot/scan/data.json", "screenshot/scan/images"),
SIMILAR_PHOTOS("similar_photos/scan/data.json", "similar_photos/scan/images"),
WHATSAPP("whatsapp/scan/data.json", "whatsapp/scan/images"),
CLEAN("clean.json")
}
\ No newline at end of file
package com.base.pdfviewerscannerwhite.mix
import android.annotation.SuppressLint
import android.content.Context
import android.database.Cursor
import android.media.MediaScannerConnection
import android.net.Uri
import android.provider.MediaStore
import java.io.File
import java.text.SimpleDateFormat
import java.util.Locale
object MediaHelps {
private val projection = arrayOf(
MediaStore.Files.FileColumns.DISPLAY_NAME,
MediaStore.Files.FileColumns.DATA,
MediaStore.Files.FileColumns.SIZE,
MediaStore.Files.FileColumns.DATE_MODIFIED,
MediaStore.Files.FileColumns.MIME_TYPE
)
private const val EXTERNAL = "external"
fun updateMedia(context:Context, paths: Array<String>) {
MediaScannerConnection.scanFile(context, paths, null, null)
}
fun findFiles(context: Context, size: Long = 0): List<FileBean> {
return queryFilesWithSize(context, MediaStore.Files.getContentUri(EXTERNAL), size)
}
fun findSpecifiedFiles(context: Context): List<FileBean> {
val suffixes = arrayOf("%.log", "%.apk", "%.aab", "%.temp", "%.LOG", "%.APK", "%.AAB", "%.TEMP")
return queryFilesWithSuffixes(context, MediaStore.Files.getContentUri(EXTERNAL), suffixes)
}
fun findScreenshotsFiles(context: Context): Map<String, MutableList<FileBean>> {
val selection = "${MediaStore.Images.Media.RELATIVE_PATH} LIKE ?"
val selectionArgs = arrayOf("%Screenshots%")
val list = query(context, MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection, selection, selectionArgs, projection[3])
val map = mutableMapOf<String, MutableList<FileBean>>()
val dateFormat = SimpleDateFormat("yyyy/MM", Locale.getDefault())
list.forEach { map.getOrPut(dateFormat.format(it.lastModified)) { mutableListOf() }.add(it) }
return map
}
fun findImageFiles(context: Context, size: Long = 0): List<FileBean> {
return queryFilesWithSize(context, MediaStore.Images.Media.EXTERNAL_CONTENT_URI, size)
}
fun findVideoFiles(context: Context, size: Long = 0): List<FileBean> {
return queryFilesWithSize(context, MediaStore.Video.Media.EXTERNAL_CONTENT_URI, size)
}
fun findAudioFiles(context: Context, size: Long = 0): List<FileBean> {
return queryFilesWithSize(context, MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, size)
}
fun findDocFiles(context: Context, size: Long = 0): List<FileBean> {
val mimeTypes = arrayOf(
"text/plain",
"application/msword",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"application/vnd.ms-excel",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"application/pdf",
)
return queryFilesWithMimeTypes(context, MediaStore.Files.getContentUri(EXTERNAL), mimeTypes, size)
}
private fun queryFilesWithSuffixes(context: Context, uri: Uri, suffixes: Array<String>): List<FileBean> {
val selection = suffixes.joinToString(separator = " OR ") { "${MediaStore.Files.FileColumns.DISPLAY_NAME} LIKE ?" }
return query(context, uri, projection, selection, suffixes)
}
private fun queryFilesWithSize(context: Context, uri: Uri, size: Long): List<FileBean> {
var selection: String? = null
var selectionArgs: Array<String>? = null
if (size > 0) {
selection = "${MediaStore.Files.FileColumns.SIZE} >= ?"
selectionArgs = arrayOf(size.toString())
}
return query(context, uri, projection, selection, selectionArgs)
}
private fun queryFilesWithMimeTypes(context: Context, uri: Uri, mimeTypes: Array<String>, size: Long): List<FileBean> {
val (selection, selectionArgs) = buildSelectionWithMimeTypes(mimeTypes, size)
return query(context, uri, projection, selection, selectionArgs)
}
private fun buildSelectionWithMimeTypes(mimeTypes: Array<String>, size: Long): Pair<String, Array<String>> {
val mimeTypeConditions = mimeTypes.joinToString(separator = " OR ") { "${MediaStore.Files.FileColumns.MIME_TYPE}=?" }
val sizeCondition = "${MediaStore.Files.FileColumns.SIZE} >=?"
val selection = "($mimeTypeConditions) AND ($sizeCondition)"
val selectionArgs = mimeTypes + size.toString()
return selection to selectionArgs
}
private fun buildSelectionWithMimeTypes(mimeTypes: Array<String>): Pair<String, Array<String>> {
val selection = mimeTypes.joinToString(prefix = "${MediaStore.Files.FileColumns.MIME_TYPE}=?", separator = " OR ") { "'$it'" }
val selectionArgs = mimeTypes
return Pair(selection, selectionArgs)
}
@SuppressLint("Range")
private fun query(
context: Context,
uri: Uri,
projection: Array<String>,
selection: String? = null,
selectionArgs: Array<String>? = null,
sortOrder: String = MediaStore.Files.FileColumns.DATE_MODIFIED
): List<FileBean> {
val list = mutableListOf<FileBean>()
var cursor: Cursor? = null
try {
val contentResolver = context.contentResolver
cursor = contentResolver.query(
uri,
projection,
selection,
selectionArgs,
"${sortOrder} DESC"
)
cursor?.let {
while (it.moveToNext()) {
val filePath = it.getString(it.getColumnIndex(projection[1]))
if (!File(filePath).exists()) continue
val displayName = it.getString(it.getColumnIndex(projection[0]))
val size = it.getLong(it.getColumnIndex(projection[2]))
val dateModified = it.getLong(it.getColumnIndex(projection[3])) * 1000
val mineType = it.getString(it.getColumnIndex(projection[4]))
list.add(FileBean(displayName, filePath, 0, size, dateModified, mineType))
}
}
} catch (e: Exception) {
e.printStackTrace()
} finally {
cursor?.close()
}
return list
}
}
\ No newline at end of file
package com.base.pdfviewerscannerwhite.mix
import android.webkit.MimeTypeMap
object MineTypeHelps {
val TYPE_VIDEO = 0
val TYPE_IMAGE = 1
val TYPE_AUDIO = 2
val mineTypes by lazy {
listOf(
"image/",
"video/",
"audio/",
"text/",
MimeTypeMap.getSingleton().getMimeTypeFromExtension("pdf") ?: "",
MimeTypeMap.getSingleton().getMimeTypeFromExtension("doc") ?: "",
MimeTypeMap.getSingleton().getMimeTypeFromExtension("docx") ?: "",
MimeTypeMap.getSingleton().getMimeTypeFromExtension("xls") ?: "",
MimeTypeMap.getSingleton().getMimeTypeFromExtension("xlsx") ?: "",
MimeTypeMap.getSingleton().getMimeTypeFromExtension("ppt") ?: "",
MimeTypeMap.getSingleton().getMimeTypeFromExtension("apk") ?: "",
)
}
val images = listOf(".jpeg", ".jpg", ".png", ".gif", ".webp", ".ico", ".raw") // 图像
val videos = listOf(".mp4", ".avi", ".mov", ".wmv", ".flv") // 视频
val audios = listOf(".mp3", ".wav", ".m4a", ".ncm") // 音频
fun isImage(mineType: String): Boolean {
return mineType.startsWith(mineTypes[0])
}
fun isVideo(mineType: String): Boolean {
return mineType.startsWith(mineTypes[1])
}
fun isAudio(mineType: String): Boolean {
return mineType.startsWith(mineTypes[2])
}
fun isDoc(mineType: String): Boolean {
return mineType.startsWith(mineTypes[3])
|| mineType.startsWith(mineTypes[4])
|| mineType.startsWith(mineTypes[5])
|| mineType.startsWith(mineTypes[6])
|| mineType.startsWith(mineTypes[7])
|| mineType.startsWith(mineTypes[8])
|| mineType.startsWith(mineTypes[9])
}
fun isApk(mineType: String): Boolean {
return mineType.startsWith(mineTypes[10])
}
}
\ No newline at end of file
package com.base.pdfviewerscannerwhite.mix
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.TextView
import androidx.annotation.LayoutRes
import com.applovin.mediation.MaxAd
import com.applovin.mediation.nativeAds.MaxNativeAdLoader
import com.applovin.mediation.nativeAds.MaxNativeAdView
import com.applovin.mediation.nativeAds.MaxNativeAdViewBinder
import com.base.pdfviewerscannerwhite.R
import com.google.android.gms.ads.nativead.NativeAd
import com.google.android.gms.ads.nativead.NativeAdView
class NativeView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null
): FrameLayout(context, attrs) {
fun setExitNativeAd(nativeAd: NativeAd) {
setNativeAd(nativeAd, R.layout.layout_ad_native_exit)
}
fun setExitNativeAd(
nativeAdLoader: MaxNativeAdLoader,
nativeAd: MaxAd,
@LayoutRes resource: Int = R.layout.layout_ad_native_exit
) {
setNativeAd(nativeAdLoader, nativeAd, resource)
}
fun setNativeAd(
nativeAdLoader: MaxNativeAdLoader,
nativeAd: MaxAd,
@LayoutRes resource: Int = R.layout.layout_ad_native
) {
val builder = MaxNativeAdViewBinder.Builder(resource)
.setTitleTextViewId(R.id.ad_headline)
.setIconImageViewId(R.id.ad_icon)
.setMediaContentViewGroupId(R.id.ad_media)
.setCallToActionButtonId(R.id.ad_call_to_action)
if (resource != R.layout.layout_ad_native)
builder.setBodyTextViewId(R.id.ad_body)
visibility = VISIBLE
val adView = MaxNativeAdView(builder.build(), context)
nativeAdLoader.render(adView, nativeAd)
removeAllViews()
addView(adView)
}
fun setNativeAd(nativeAd: NativeAd, @LayoutRes resource: Int ?= R.layout.layout_ad_native) {
visibility = VISIBLE
val adView = resource?.let { LayoutInflater.from(context).inflate(it, null) } as NativeAdView
adView.mediaView = adView.findViewById(R.id.ad_media)
adView.headlineView = adView.findViewById(R.id.ad_headline)
adView.callToActionView = adView.findViewById(R.id.ad_call_to_action)
adView.iconView = adView.findViewById(R.id.ad_icon)
(adView.headlineView as TextView?)?.text = nativeAd.headline
adView.mediaView!!.mediaContent = nativeAd.mediaContent
if (nativeAd.callToAction != null) {
(adView.callToActionView as TextView?)?.text = nativeAd.callToAction
}
if (nativeAd.icon != null) {
(adView.iconView as ImageView?)?.setImageDrawable(nativeAd.icon!!.drawable)
}
val body = adView.findViewById<TextView>(R.id.ad_body)
if (body != null) {
adView.bodyView = body
if (nativeAd.body == null) {
adView.bodyView?.visibility = GONE
} else {
adView.bodyView?.visibility = VISIBLE
(adView.bodyView as TextView?)?.text = nativeAd.body
}
}
adView.setNativeAd(nativeAd)
removeAllViews()
addView(adView)
}
}
\ No newline at end of file
package com.base.pdfviewerscannerwhite.mix
import android.Manifest
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.Settings
import androidx.core.app.NotificationManagerCompat
import androidx.core.content.ContextCompat
import com.base.pdfviewerscannerwhite.utils.ActivityLauncher
object PermissionHelps {
fun requestFilesAccessPermission(
context: Context,
launcher: ActivityLauncher,
result: (Boolean) -> Unit
) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
try {
val intent = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION)
intent.addCategory("android.intent.category.DEFAULT")
intent.data = Uri.parse("package:${context.packageName}")
launcher.launch(intent) {
result.invoke(checkFilesAccessPermission(context))
}
} catch (_: Exception) {
}
} else {
val array = arrayOf(
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
)
launcher.launch(array) { permissions ->
result(permissions.values.all { it })
}
}
}
fun requestNotificationPermission(
context: Context,
launcher: ActivityLauncher,
result: (Boolean) -> Unit
) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
val array = arrayOf(Manifest.permission.POST_NOTIFICATIONS)
launcher.launch(array) { permissions ->
val flag = permissions.values.all { it }
if (!flag) notificationSettings(context, launcher, result)
}
} else {
notificationSettings(context, launcher, result)
}
}
fun notificationSettings(
context: Context,
launcher: ActivityLauncher,
result: (Boolean) -> Unit
) {
val intent = Intent()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
intent.action = Settings.ACTION_APP_NOTIFICATION_SETTINGS
intent.putExtra(Settings.EXTRA_APP_PACKAGE, context.packageName)
} else {
intent.action = "android.settings.APP_NOTIFICATION_SETTINGS"
intent.putExtra("app_package", context.packageName)
}
launcher.launch(intent) {
result.invoke(checkNotificationPermission(context))
}
}
fun checkNotificationPermission(context: Context): Boolean {
return NotificationManagerCompat.from(context).areNotificationsEnabled()
}
fun checkFilesAccessPermission(context: Context): Boolean {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
return Environment.isExternalStorageManager()
} else {
val readPermission = ContextCompat.checkSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE)
val writePermission = ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE)
return readPermission == PackageManager.PERMISSION_GRANTED && writePermission == PackageManager.PERMISSION_GRANTED
}
}
}
\ No newline at end of file
package com.base.pdfviewerscannerwhite.mix
import android.app.Activity
import android.os.Bundle
import com.base.pdfviewerscannerwhite.helper.EventUtils
import com.base.pdfviewerscannerwhite.helper.MyApplication
import com.facebook.appevents.AppEventsConstants
import com.facebook.appevents.AppEventsLogger
import com.google.android.gms.ads.AdValue
import com.google.android.gms.ads.OnPaidEventListener
import com.google.android.gms.ads.ResponseInfo
import com.google.android.gms.ads.appopen.AppOpenAd
import com.google.android.gms.ads.interstitial.InterstitialAd
import com.google.android.gms.ads.nativead.NativeAd
import com.google.android.gms.ads.rewarded.RewardedAd
import com.google.firebase.analytics.FirebaseAnalytics
import com.google.firebase.analytics.ktx.analytics
import com.google.firebase.ktx.Firebase
import org.json.JSONObject
import kotlin.random.Random
object ReportAdUtils {
private val taichiPref by lazy {
MyApplication.context.getSharedPreferences("TaichiTroasCache", 0)
}
private val taichiSharedPreferencesEditor by lazy {
taichiPref.edit()
}
fun pullStartAd(
reqId: String,
adUnit: String,
className: String,
) {
val obj = JSONObject()
obj.put("req_id", reqId)
obj.put("ad_unit", adUnit)
obj.put("from", className)
EventUtils.event("ad_pull_start", "", ext = obj)
}
fun pullAd(
responseInfo: ResponseInfo?,
adUnit: String,
error: String? = null,
reqId: String? = null
) {
val obj = JSONObject()
if (responseInfo != null) {
val response = responseInfo.adapterResponses.getOrNull(0)
if (response != null) {
obj.put("source", response.adSourceName)
val credentials = mapOf(
"placementid" to response.credentials.get("placementid"),
"appid" to response.credentials.get("appid"),
"pubid" to response.credentials.get("pubid")
)
obj.put("credentials", credentials.toString())
}
obj.put("session_id", responseInfo.responseId)
}
obj.put("networkname", responseInfo?.mediationAdapterClassName)
obj.put("ad_unit", adUnit)
obj.put("req_id", reqId)
obj.put("mediation", "admob")
if (error == null) {
obj.put("status", "1")
} else {
obj.put("errMsg", error)
obj.put("status", "2")
}
EventUtils.event("ad_pull", "", ext = obj)
}
class EventOnPaidEventListener(private val ad: Any?) : OnPaidEventListener {
override fun onPaidEvent(adValue: AdValue) {
val adRatio = SpUtils.getInstance().getInt("adRatio", 100)
val random = Random.Default.nextInt(1, 100)
if (random > adRatio) {
taichiSharedPreferencesEditor.putFloat("TaichiTroasCache", 0f)
taichiSharedPreferencesEditor.commit()
EventUtils.event("ad_price_limit")
return
}
val valueMicros = adValue.valueMicros
val currencyCode = adValue.currencyCode
val precision = adValue.precisionType
val obj = JSONObject()
obj.put("valueMicros", valueMicros)
obj.put("currencyCode", currencyCode)
obj.put("precision", precision)
Firebase.analytics.logEvent("ad_price", Bundle().apply {
putDouble("valueMicros", valueMicros / 1000000.0)
})
val params = Bundle()
val currentImpressionRevenue = adValue.valueMicros.toDouble() / 1000000.0
params.putDouble(FirebaseAnalytics.Param.VALUE, currentImpressionRevenue)
params.putString(FirebaseAnalytics.Param.CURRENCY, "USD")
val precisionType = when (adValue.precisionType) {
0 -> "UNKNOWN"
1 -> "ESTIMATED"
2 -> "PUBLISHER_PROVIDED"
3 -> "PRECISE"
else -> "Invalid"
}
params.putString("precisionType", precisionType)
Firebase.analytics.logEvent("Ad_Impression_Revenue", params)
val previousTaichiTroasCache = taichiPref.getFloat("TaichiTroasCache", 0f)
val currentTaichiTroasCache = (previousTaichiTroasCache +
currentImpressionRevenue)
val adValue = SpUtils.getInstance().getInt("adValue", 1) / 100f
if (currentTaichiTroasCache >= adValue) {//如果超过0.01就触发一次tROAS taichi事件
val roasbundle = Bundle()
roasbundle.putDouble(
FirebaseAnalytics.Param.VALUE,
currentTaichiTroasCache
)
roasbundle.putString(FirebaseAnalytics.Param.CURRENCY, "USD")
Firebase.analytics.logEvent("Total_Ads_Revenue_001", roasbundle)
taichiSharedPreferencesEditor.putFloat("TaichiTroasCache", 0f)//重新清零,开始计算
val logger = AppEventsLogger.newLogger(MyApplication.context)
val parameters = Bundle()
parameters.putString(AppEventsConstants.EVENT_PARAM_CURRENCY, "USD")
logger.logEvent("ad_value", currentTaichiTroasCache, parameters)
} else {
taichiSharedPreferencesEditor.putFloat("TaichiTroasCache", currentTaichiTroasCache.toFloat())
}
taichiSharedPreferencesEditor.commit()
when (ad) {
is AppOpenAd -> {
val adUnitId = ad.adUnitId
val loadedAdapterResponseInfo = ad.responseInfo.loadedAdapterResponseInfo
val adSourceName = loadedAdapterResponseInfo?.adSourceName
val adSourceId = loadedAdapterResponseInfo?.adSourceId
val adSourceInstanceName = loadedAdapterResponseInfo?.adSourceInstanceName
val adSourceInstanceId = loadedAdapterResponseInfo?.adSourceInstanceId
val sessionId = ad.responseInfo.responseId
val extras = ad.responseInfo.responseExtras
val mediationGroupName = extras.getString("mediation_group_name")
val mediationABTestName = extras.getString("mediation_ab_test_name")
val mediationABTestVariant = extras.getString("mediation_ab_test_variant")
obj.put("adUnitId", adUnitId)
obj.put("adSourceName", adSourceName)
obj.put("adSourceId", adSourceId)
obj.put("adSourceInstanceName", adSourceInstanceName)
obj.put("adSourceInstanceId", adSourceInstanceId)
obj.put("mediationGroupName", mediationGroupName)
obj.put("mediationABTestName", mediationABTestName)
obj.put("mediationABTestVariant", mediationABTestVariant)
obj.put("session_id", sessionId)
}
is InterstitialAd -> {
val adUnitId = ad.adUnitId
val loadedAdapterResponseInfo = ad.responseInfo.loadedAdapterResponseInfo
val adSourceName = loadedAdapterResponseInfo?.adSourceName
val adSourceId = loadedAdapterResponseInfo?.adSourceId
val adSourceInstanceName = loadedAdapterResponseInfo?.adSourceInstanceName
val adSourceInstanceId = loadedAdapterResponseInfo?.adSourceInstanceId
val sessionId = ad.responseInfo.responseId
val extras = ad.responseInfo.responseExtras
val mediationGroupName = extras.getString("mediation_group_name")
val mediationABTestName = extras.getString("mediation_ab_test_name")
val mediationABTestVariant = extras.getString("mediation_ab_test_variant")
obj.put("adUnitId", adUnitId)
obj.put("adSourceName", adSourceName)
obj.put("adSourceId", adSourceId)
obj.put("adSourceInstanceName", adSourceInstanceName)
obj.put("adSourceInstanceId", adSourceInstanceId)
obj.put("mediationGroupName", mediationGroupName)
obj.put("mediationABTestName", mediationABTestName)
obj.put("mediationABTestVariant", mediationABTestVariant)
obj.put("session_id", sessionId)
}
is RewardedAd -> {
val loadedAdapterResponseInfo = ad.responseInfo.loadedAdapterResponseInfo
val adSourceName = loadedAdapterResponseInfo?.adSourceName
val adSourceId = loadedAdapterResponseInfo?.adSourceId
val adSourceInstanceName = loadedAdapterResponseInfo?.adSourceInstanceName
val adSourceInstanceId = loadedAdapterResponseInfo?.adSourceInstanceId
val sessionId = ad.responseInfo.responseId
val extras = ad.responseInfo.responseExtras
val mediationGroupName = extras.getString("mediation_group_name")
val mediationABTestName = extras.getString("mediation_ab_test_name")
val mediationABTestVariant = extras.getString("mediation_ab_test_variant")
obj.put("adSourceName", adSourceName)
obj.put("adSourceId", adSourceId)
obj.put("adSourceInstanceName", adSourceInstanceName)
obj.put("adSourceInstanceId", adSourceInstanceId)
obj.put("mediationGroupName", mediationGroupName)
obj.put("mediationABTestName", mediationABTestName)
obj.put("mediationABTestVariant", mediationABTestVariant)
obj.put("session_id", sessionId)
}
is NativeAd -> {
val loadedAdapterResponseInfo = ad.responseInfo?.loadedAdapterResponseInfo
val adSourceName = loadedAdapterResponseInfo?.adSourceName
val adSourceId = loadedAdapterResponseInfo?.adSourceId
val adSourceInstanceName = loadedAdapterResponseInfo?.adSourceInstanceName
val adSourceInstanceId = loadedAdapterResponseInfo?.adSourceInstanceId
val sessionId = ad.responseInfo?.responseId
val extras = ad.responseInfo?.responseExtras
val mediationGroupName = extras?.getString("mediation_group_name")
val mediationABTestName = extras?.getString("mediation_ab_test_name")
val mediationABTestVariant = extras?.getString("mediation_ab_test_variant")
obj.put("adSourceName", adSourceName)
obj.put("adSourceId", adSourceId)
obj.put("adSourceInstanceName", adSourceInstanceName)
obj.put("adSourceInstanceId", adSourceInstanceId)
obj.put("mediationGroupName", mediationGroupName)
obj.put("mediationABTestName", mediationABTestName)
obj.put("mediationABTestVariant", mediationABTestVariant)
obj.put("session_id", sessionId)
obj.put("adUnitId", "nativeAd")
}
}
EventUtils.event("ad_price", "", ext = obj)
}
}
fun clickAd(responseInfo: ResponseInfo?, adUnit: String) {
val response = responseInfo?.adapterResponses?.getOrNull(0)
val obj = JSONObject()
obj.put("source", response?.adSourceName)
obj.put("ad_unit", adUnit)
val credentials = mapOf(
"placementid" to response?.credentials?.get("placementid"),
"appid" to response?.credentials?.get("appid"),
"pubid" to response?.credentials?.get("pubid")
)
obj.put("credentials", credentials.toString())
obj.put("session_id", responseInfo?.responseId)
obj.put("networkname", responseInfo?.mediationAdapterClassName)
obj.put("mediation", "admob")
EventUtils.event("ad_click", "", ext = obj)
}
fun showAd(responseInfo: ResponseInfo?, adUnit: String, activity: Activity? = null) {
val response = responseInfo?.adapterResponses?.getOrNull(0)
val obj = JSONObject()
obj.put("source", response?.adSourceName)
obj.put("ad_unit", adUnit)
obj.put("networkname", responseInfo?.mediationAdapterClassName)
val credentials = mapOf(
"placementid" to response?.credentials?.get("placementid"),
"appid" to response?.credentials?.get("appid"),
"pubid" to response?.credentials?.get("pubid")
)
obj.put("credentials", credentials.toString())
obj.put("session_id", responseInfo?.responseId)
obj.put("from", activity?.javaClass?.simpleName)
obj.put("mediation", "admob")
EventUtils.event("ad_show", "", ext = obj)
}
fun showErrorAd(reason: String, adUnit: String) {
val obj = JSONObject()
obj.put("reason", reason)
obj.put("ad_unit", adUnit)
EventUtils.event("ad_show_error", "", ext = obj)
}
fun showPrepareAd(adUnit: String) {
val obj = JSONObject()
obj.put("ad_unit", adUnit)
EventUtils.event("ad_prepare_show", "", ext = obj)
}
fun limitErrorAd(reason: String, adUnit: String) {
val obj = JSONObject()
obj.put("reason", reason)
obj.put("ad_unit", adUnit)
EventUtils.event("ad_limit_error", "", ext = obj)
}
}
\ No newline at end of file
package com.base.pdfviewerscannerwhite.mix
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.View
import androidx.activity.addCallback
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.GridLayoutManager
import com.base.pdfviewerscannerwhite.R
import com.base.pdfviewerscannerwhite.ads.admob.AdmobInterstitialUtils
import com.base.pdfviewerscannerwhite.bean.ConstObject
import com.base.pdfviewerscannerwhite.databinding.ActivityScreenshotCleanBinding
import com.base.pdfviewerscannerwhite.ui.result.ResultActivity
import com.base.pdfviewerscannerwhite.utils.LogEx
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import pokercc.android.expandablerecyclerview.ExpandableAdapter
class ScreenshotCleanActivity : BaseActivity2() {
companion object {
fun start(context: Context) {
val intent = Intent(context, ScreenshotCleanActivity::class.java)
context.startActivity(intent)
}
}
private val binding by lazy {
ActivityScreenshotCleanBinding.inflate(layoutInflater)
}
private lateinit var adapter: ScreenshotCleanAdapter
private var total: Long = 0
private var isSelectAll = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
initView()
initData()
showAnimationAd(LottieType.SCREENSHOT) {
}
onBackPressedDispatcher.addCallback {
handleBackPressed(this@ScreenshotCleanActivity)
}
}
private fun initView() {
adapter = ScreenshotCleanAdapter()
adapter.selectionData.observe(this) { list ->
isSelectAll = list.stream().allMatch(FileBean::isSelected)
val selectionList = list.filter { it.isSelected }
total = selectionList.sumOf { it.length }
updateView(selectionList.isNotEmpty())
}
binding.expandableFiles.adapter = adapter
val gridLayoutManager = GridLayoutManager(this, 3)
gridLayoutManager.spanSizeLookup = MediaImageSpanLookup(3, adapter)
binding.expandableFiles.layoutManager = gridLayoutManager
binding.flBack.setOnClickListener { backPressed() }
binding.llSelectAll.setOnClickListener {
isSelectAll = !isSelectAll
adapter.child.flatten().forEach { it.isSelected = isSelectAll }
adapter.setData(adapter.group, adapter.child)
total = adapter.child.flatten().filter { it.isSelected }.sumOf { it.length }
updateView(isSelectAll)
}
binding.tvDelete.setOnClickListener {
if (total <= 0) return@setOnClickListener
DialogHelps.showDeleteDialog(this, binding.tvDelete) {
AdmobInterstitialUtils.showInterstitialAd(this, false, false) {
startActivity(Intent(this, ResultActivity::class.java).apply {
putExtra("from", ConstObject.FUNCTION_SCREEN_SHORT)
putExtra("clean_size", total)
LogEx.logDebug("clean_size", "total=$total")
})
finish()
}
cleanFiles(adapter.child.flatten())
}
}
}
private fun initData() {
lifecycleScope.launch(Dispatchers.IO) {
val screenFiles = MediaHelps.findScreenshotsFiles(this@ScreenshotCleanActivity)
val total = screenFiles.values.toList().flatten().sumOf { it.length }
val value = Utils.getSizeArray(total)
withContext(Dispatchers.Main) {
binding.tvSize.text = value[0]
binding.tvUnit.text = value[1]
adapter.setData(screenFiles.keys.toList(), screenFiles.values.toList())
adapter.expandAllGroup()
binding.ivEmpty.visibility = if (screenFiles.isEmpty()) View.VISIBLE else View.GONE
binding.llBottom.visibility = if (screenFiles.isEmpty()) View.GONE else View.VISIBLE
}
}
}
private fun updateView(isSelection: Boolean) {
binding.ivSelectAll.setImageResource(if (isSelectAll) R.mipmap.ic_check_s else R.mipmap.ic_check_n)
binding.tvDelete.setBackgroundResource(if (isSelection) R.drawable.gradient_26 else R.drawable.btn_not_clickable)
val delete = getString(R.string.delete)
val text = if (total > 0) "${delete} (${Utils.getSize(total)})" else delete
binding.tvDelete.text = text
}
}
internal class MediaImageSpanLookup(
private val spanCount: Int,
private val expandableAdapter: ExpandableAdapter<*>
) :
GridLayoutManager.SpanSizeLookup() {
override fun getSpanSize(position: Int): Int {
val viewType = expandableAdapter.getItemViewType(position)
return if (expandableAdapter.isGroup(viewType)) spanCount else 1
}
}
\ No newline at end of file
package com.base.pdfviewerscannerwhite.mix
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.base.pdfviewerscannerwhite.R
import com.base.pdfviewerscannerwhite.databinding.ItemChildScreenshotCleanBinding
import com.base.pdfviewerscannerwhite.databinding.ItemGroupScreenshotCleanBinding
import com.base.pdfviewerscannerwhite.mix.AppHelps.dpToPx
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.bitmap.CenterCrop
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
import com.bumptech.glide.request.RequestOptions
import pokercc.android.expandablerecyclerview.ExpandableAdapter
class ScreenshotCleanAdapter(
var group: List<String>,
var child: List<List<FileBean>>
) : ExpandableAdapter<ExpandableAdapter.ViewHolder>() {
constructor() : this(emptyList(), emptyList())
private val _selectionData = MutableLiveData<List<FileBean>>()
val selectionData: LiveData<List<FileBean>> = _selectionData
fun setData(group: List<String>, child: List<List<FileBean>>) {
this.group = group
this.child = child
notifyDataSetChanged()
}
override fun getChildCount(groupPosition: Int): Int {
if (child.isEmpty() || child.size <= groupPosition) {
return 0
}
return child[groupPosition].size
}
override fun getGroupCount(): Int {
return group.size
}
override fun onCreateChildViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder {
val inflater = LayoutInflater.from(viewGroup.context)
val view = ItemChildScreenshotCleanBinding.inflate(inflater, viewGroup, false)
return ChildViewHolder(view)
}
override fun onCreateGroupViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder {
val inflater = LayoutInflater.from(viewGroup.context)
val view = ItemGroupScreenshotCleanBinding.inflate(inflater, viewGroup, false)
return GroupViewHolder(view)
}
override fun onGroupViewHolderExpandChange(
holder: ViewHolder,
groupPosition: Int,
animDuration: Long,
expand: Boolean
) {
}
override fun onBindGroupViewHolder(
holder: ViewHolder,
groupPosition: Int,
expand: Boolean,
payloads: List<Any>
) {
holder as GroupViewHolder
holder.binding.tvName.text = group[groupPosition]
holder.binding.viewBg.visibility = if (groupPosition == 0) View.GONE else View.VISIBLE
holder.itemView.setOnClickListener { }
}
override fun onBindChildViewHolder(
holder: ViewHolder,
groupPosition: Int,
childPosition: Int,
payloads: List<Any>
) {
holder as ChildViewHolder
val data = child[groupPosition][childPosition]
val width = holder.itemView.context.resources.displayMetrics.widthPixels
var margin = holder.itemView.context.dpToPx(44).toInt()
val imageWidth = (width - margin) / 3
holder.binding.ivImage.layoutParams.width = imageWidth
holder.binding.ivImage.layoutParams.height = imageWidth
margin = holder.itemView.context.dpToPx(15).toInt()
if (childPosition % 3 == 0) {
holder.itemView.setPadding(margin, 0, 0, 0)
} else if (childPosition % 3 == 2) {
holder.itemView.setPadding(0, 0, margin, 0)
} else {
holder.itemView.setPadding(margin / 2, 0, margin / 2, 0)
}
val round = holder.itemView.context.dpToPx(8).toInt()
val options = RequestOptions().transform(CenterCrop(), RoundedCorners(round))
Glide.with(holder.itemView.context)
.load(data.path)
.apply(options)
.into(holder.binding.ivImage)
holder.binding.tvSize.text = Utils.getSize(data.length)
holder.binding.ivSelect.setImageResource(if (data.isSelected) R.mipmap.ic_check_s else R.mipmap.ic_check_n)
holder.binding.clContainer.setOnClickListener {
data.isSelected = !data.isSelected
holder.binding.ivSelect.setImageResource(if (data.isSelected) R.mipmap.ic_check_s else R.mipmap.ic_check_n)
_selectionData.value = child.flatten()
}
}
}
private class ChildViewHolder(val binding: ItemChildScreenshotCleanBinding) :
ExpandableAdapter.ViewHolder(binding.root)
private class GroupViewHolder(val binding: ItemGroupScreenshotCleanBinding) :
ExpandableAdapter.ViewHolder(binding.root)
\ No newline at end of file
package com.base.pdfviewerscannerwhite.mix
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.View
import androidx.activity.addCallback
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import com.base.pdfviewerscannerwhite.R
import com.base.pdfviewerscannerwhite.bean.SimilarBean
import com.base.pdfviewerscannerwhite.databinding.ActivitySimilarPhotosBinding
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.util.concurrent.Semaphore
class SimilarPhotosActivity : BaseActivity2() {
companion object {
fun start(context: Context) {
val intent = Intent(context, SimilarPhotosActivity::class.java)
context.startActivity(intent)
}
}
private lateinit var adapter: SimilarPhotosAdapter
private val semaphore = Semaphore(20)
private var isScanning = true
private val binding by lazy {
ActivitySimilarPhotosBinding.inflate(layoutInflater)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
initView()
initData()
showAnimationAd(LottieType.SIMILAR_PHOTOS) {
if (isScanning) {
// loadingDialog = DialogHelps.showLoadingDialog(this)
}
}
AdmobHelps.showNativeAd(this, completed = {
binding.adNative.setNativeAd(it)
}, maxCompleted = { nativeAdLoader, nativeMaxAd ->
binding.adNative.setNativeAd(nativeAdLoader, nativeMaxAd)
})
onBackPressedDispatcher.addCallback {
handleBackPressed(this@SimilarPhotosActivity)
}
}
private fun initView() {
adapter = SimilarPhotosAdapter()
adapter.callback = object : BaseAdapter.OnClickCallback<SimilarBean> {
override fun onClicked(view: View, position: Int, item: SimilarBean) {
val list = getAllList(adapter.list)
val total = list.filter { it.isSelect }.sumOf { it.size }
showSelection(total > 0, total)
}
}
binding.rvPhoto.adapter = adapter
binding.rvPhoto.layoutManager = LinearLayoutManager(this)
binding.flBack.setOnClickListener { backPressed() }
binding.ivSelect.setOnCheckedChangeListener { _, isChecked ->
setSelectAll(isChecked, adapter.list)
}
binding.tvDelete.setOnClickListener {
val list = getAllList(adapter.list).filter { it.isSelect }
if (list.isEmpty()) return@setOnClickListener
val total = list.sumOf { it.size }
DialogHelps.showDeleteDialog(this, binding.tvDelete) {
showAnimationAd {
}
deleteFiles(list)
}
}
}
private fun initData() {
lifecycleScope.launch(Dispatchers.IO) {
val images = MediaHelps.findImageFiles(this@SimilarPhotosActivity)
val similarBeans = images.mapNotNull { value ->
lifecycleScope.async(Dispatchers.IO) {
semaphore.acquire() // 请求许可
try {
ImageHelpers.createImage(value.path)
} finally {
semaphore.release() // 释放许可
}
}.await()
}
// val similarBeans = deferredSimilarBeans.mapNotNull { it.await() }
val hasSame = mutableSetOf<String>()
similarBeans.forEach { similar ->
if (hasSame.contains(similar.url)) return@forEach
hasSame.add(similar.url)
similar.items.add(similar)
similarBeans.forEach {
if (!hasSame.contains(it.url) && ImageHelpers.similarCondition(similar, it)) {
hasSame.add(it.url)
similar.items.add(it)
}
}
}
val list = similarBeans.filter { it.items.size > 1 }
withContext(Dispatchers.Main) {
isScanning = false
loadingDialog?.dismiss()
setSelectAll(true, list)
}
}
}
private fun setSelectAll(isSelected: Boolean, list: List<SimilarBean>) {
binding.ivSelect.isSelected = isSelected
list.forEach { similar ->
similar.items.forEachIndexed { index, similarBean ->
similarBean.isSelect = if (index > 0) isSelected else false
}
}
adapter.submitList(list)
val total = getAllList(adapter.list).filter { it.isSelect }.sumOf { it.size }
showSelection(isSelected && list.isNotEmpty(), total)
}
private fun deleteFiles(list: List<SimilarBean>) {
lifecycleScope.launch(Dispatchers.IO) {
val paths = list.map { it.url }.toTypedArray()
paths.forEach { FileHelps.deleteFile(it) }
withContext(Dispatchers.Main) {
MediaHelps.updateMedia(applicationContext, paths)
}
}
}
private fun showSelection(isSelection: Boolean, total: Long) {
binding.tvDelete.setBackgroundResource(if (isSelection) R.drawable.gradient else R.drawable.gradient_not_clickable)
val delete = getString(R.string.delete)
binding.tvDelete.text =
if (total > 0) "${delete} (${Utils.getFormatSize(total)})" else delete
}
private fun getAllList(beans: List<SimilarBean>): MutableList<SimilarBean> {
val list = mutableListOf<SimilarBean>()
beans.forEach { it.items.forEach { list.add(it) } }
return list
}
}
\ No newline at end of file
package com.base.pdfviewerscannerwhite.mix
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.GridLayoutManager
import com.base.pdfviewerscannerwhite.R
import com.base.pdfviewerscannerwhite.bean.SimilarBean
import com.base.pdfviewerscannerwhite.databinding.ItemSimilarPhotosBinding
import com.base.pdfviewerscannerwhite.mix.AppHelps.dpToPx
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.bitmap.CenterCrop
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
import com.bumptech.glide.request.RequestOptions
class SimilarPhotosAdapter(
val data: List<SimilarBean> = emptyList()
) : BaseAdapter<SimilarBean, ItemSimilarPhotosBinding>(data) {
override fun getViewBinding(
layoutInflater: LayoutInflater,
parent: ViewGroup
): ItemSimilarPhotosBinding {
return ItemSimilarPhotosBinding.inflate(layoutInflater, parent, false)
}
override fun bind(
holder: BaseViewHolder<ItemSimilarPhotosBinding>,
position: Int,
item: SimilarBean
) {
val total = item.items.filter { it.isSelect }.sumOf { it.size }
holder.binding.tvSize.text = Utils.getFormatSize(total)
val width = holder.itemView.context.resources.displayMetrics.widthPixels
val margin = holder.itemView.context.dpToPx(45).toInt()
val imageWidth = (width - margin) / 4
val largePhotoWidth = imageWidth * 2
val largePhotoHeight = (largePhotoWidth * 0.92).toInt()
holder.binding.ivFirstPhoto.layoutParams.width = largePhotoWidth
holder.binding.ivFirstPhoto.layoutParams.height = largePhotoHeight
val round = holder.itemView.context.dpToPx(8).toInt()
val options = RequestOptions().transform(CenterCrop(), RoundedCorners(round))
Glide.with(holder.itemView.context)
.load(item.items[0].url)
.override(largePhotoWidth, largePhotoHeight)
.apply(options)
.into(holder.binding.ivFirstPhoto)
holder.binding.ivSelect.setImageResource(if (item.items[0].isSelect) R.mipmap.ic_check_s_photo else R.mipmap.ic_check_n_photo)
holder.binding.ivFirstPhoto.setOnClickListener {
item.items[0].isSelect = !item.items[0].isSelect
holder.binding.ivSelect.setImageResource(if (item.items[0].isSelect) R.mipmap.ic_check_s_photo else R.mipmap.ic_check_n_photo)
setItemClick(item, item.items[0], 0, holder)
}
val largePhotos = item.items.take(5)
val largeAdapter = SimilarPhotosChildAdapter(largePhotos.subList(1, largePhotos.size))
setItemClick(item, largeAdapter, holder)
holder.binding.rvLargePhoto.layoutManager = GridLayoutManager(holder.itemView.context, 2, GridLayoutManager.VERTICAL, false)
holder.binding.rvLargePhoto.adapter = largeAdapter
val photos = if (item.items.size > 4) item.items.subList(5, item.items.size) else mutableListOf()
val adapter = SimilarPhotosChildAdapter(photos)
setItemClick(item, adapter, holder)
holder.binding.rvPhoto.layoutManager = GridLayoutManager(holder.itemView.context, 4, GridLayoutManager.VERTICAL, false)
holder.binding.rvPhoto.adapter = adapter
}
private fun setItemClick(
item: SimilarBean,
adapter: SimilarPhotosChildAdapter,
holder: BaseViewHolder<ItemSimilarPhotosBinding>
) {
adapter.callback = object : OnClickCallback<SimilarBean> {
override fun onClicked(view: View, position: Int, data: SimilarBean) {
setItemClick(item, data, position, holder)
}
}
}
private fun setItemClick(
item: SimilarBean,
data: SimilarBean,
position: Int,
holder: BaseViewHolder<ItemSimilarPhotosBinding>
) {
val total = item.items.filter { it.isSelect }.sumOf { it.size }
holder.binding.tvSize.text = Utils.getFormatSize(total)
callback?.onClicked(holder.itemView, position, data)
}
}
package com.base.pdfviewerscannerwhite.mix
import android.view.LayoutInflater
import android.view.ViewGroup
import com.base.pdfviewerscannerwhite.R
import com.base.pdfviewerscannerwhite.bean.SimilarBean
import com.base.pdfviewerscannerwhite.databinding.ItemSimilarPhotosChildBinding
import com.base.pdfviewerscannerwhite.mix.AppHelps.dpToPx
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.bitmap.CenterCrop
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
import com.bumptech.glide.request.RequestOptions
class SimilarPhotosChildAdapter(
val data: List<SimilarBean>
) : BaseAdapter<SimilarBean, ItemSimilarPhotosChildBinding>(data) {
override fun getViewBinding(
layoutInflater: LayoutInflater,
parent: ViewGroup
): ItemSimilarPhotosChildBinding {
return ItemSimilarPhotosChildBinding.inflate(layoutInflater, parent, false)
}
override fun bind(
holder: BaseViewHolder<ItemSimilarPhotosChildBinding>,
position: Int,
item: SimilarBean
) {
val width = holder.itemView.context.resources.displayMetrics.widthPixels
val margin = holder.itemView.context.dpToPx(45).toInt()
val imageWidth = (width - margin) / 4
holder.binding.ivPhoto.layoutParams.width = imageWidth
holder.binding.ivPhoto.layoutParams.height = (imageWidth * 0.91).toInt()
holder.binding.ivSelect.setImageResource(if (item.isSelect) R.mipmap.ic_check_s_photo else R.mipmap.ic_check_n)
holder.itemView.setOnClickListener {
item.isSelect = !item.isSelect
holder.binding.ivSelect.setImageResource(if (item.isSelect) R.mipmap.ic_check_s_photo else R.mipmap.ic_check_n)
callback?.onClicked(it, position, item)
}
val round = holder.itemView.context.dpToPx(8).toInt()
val options = RequestOptions().transform(CenterCrop(), RoundedCorners(round))
Glide.with(holder.itemView.context)
.load(item.url)
.apply(options)
.into(holder.binding.ivPhoto)
}
}
\ No newline at end of file
package com.base.pdfviewerscannerwhite.mix
import android.content.Context
import android.content.SharedPreferences
import com.base.pdfviewerscannerwhite.helper.MyApplication
import org.json.JSONObject
class SpUtils private constructor(context: Context) {
private val sharedPreferences: SharedPreferences = context.getSharedPreferences("app_preferences", Context.MODE_PRIVATE)
// 通用的保存数据方法
fun <T> put(key: String, value: T) {
when (value) {
is String -> putString(key, value)
is Int -> putInt(key, value)
is Long -> putLong(key, value)
is Boolean -> putBoolean(key, value)
is Float -> putFloat(key, value)
else -> throw IllegalArgumentException("Unsupported type")
}
}
// 通用的获取数据方法
fun <T> get(key: String, defaultValue: T): T {
return when (defaultValue) {
is String -> getString(key, defaultValue)
is Int -> getInt(key, defaultValue)
is Long -> getLong(key, defaultValue)
is Boolean -> getBoolean(key, defaultValue)
is Float -> getFloat(key, defaultValue)
else -> throw IllegalArgumentException("Unsupported type")
} as T
}
// 保存字符串
fun putString(key: String, value: String) {
sharedPreferences.edit().putString(getKey(key), value).apply()
}
// 获取字符串
fun getString(key: String, defaultValue: String = ""): String {
return sharedPreferences.getString(getKey(key), defaultValue) ?: defaultValue
}
// 保存整数
fun putInt(key: String, value: Int) {
sharedPreferences.edit().putInt(getKey(key), value).apply()
}
// 获取整数
fun getInt(key: String, defaultValue: Int = 0): Int {
return sharedPreferences.getInt(getKey(key), defaultValue)
}
// 保存长整数
fun putLong(key: String, value: Long) {
sharedPreferences.edit().putLong(getKey(key), value).apply()
}
// 获取长整数
fun getLong(key: String, defaultValue: Long = 0): Long {
return sharedPreferences.getLong(getKey(key), defaultValue)
}
// 保存布尔值
fun putBoolean(key: String, value: Boolean) {
sharedPreferences.edit().putBoolean(getKey(key), value).apply()
}
// 获取布尔值
fun getBoolean(key: String, defaultValue: Boolean = false): Boolean {
return sharedPreferences.getBoolean(getKey(key), defaultValue)
}
// 保存浮点数
fun putFloat(key: String, value: Float) {
sharedPreferences.edit().putFloat(getKey(key), value).apply()
}
// 获取浮点数
fun getFloat(key: String, defaultValue: Float = 0f): Float {
return sharedPreferences.getFloat(getKey(key), defaultValue)
}
// 删除键值对
fun remove(key: String) {
sharedPreferences.edit().remove(getKey(key)).apply()
}
// 清除所有数据
fun clear() {
sharedPreferences.edit().clear().apply()
}
// 检查键是否存在
fun contains(key: String): Boolean {
return sharedPreferences.contains(getKey(key))
}
// 保存 JSON 对象
fun saveJsonObjectToSp(json: String) {
try {
if (json.isEmpty()) return
val jsonObject = JSONObject(json)
sharedPreferences.edit().apply {
jsonObject.keys().forEachRemaining { key ->
val value = jsonObject.get(key)
val newKey = getKey(key)
when (value) {
is String -> putString(newKey, value)
is Int -> putInt(newKey, value)
is Long -> putLong(newKey, value)
is Boolean -> putBoolean(newKey, value)
else -> putString(newKey, value.toString())
}
}
apply()
}
} catch (_:Exception) { }
}
fun <T> getValue(key: String, default: T): T {
val newKey = getKey(key)
val value = get(newKey, default)
return value
}
private fun getKey(key: String): String = "${MyApplication.context.packageName}_$key"
companion object {
@Volatile
private var instance: SpUtils? = null
// 单例模式获取实例
fun getInstance(context: Context = MyApplication.context): SpUtils {
return instance ?: synchronized(this) {
instance ?: SpUtils(context).also {
instance = it
}
}
}
}
}
\ No newline at end of file
package com.base.pdfviewerscannerwhite.mix
import android.app.Activity
import android.graphics.Color
import android.view.View
import android.view.WindowManager
import androidx.annotation.ColorInt
import androidx.core.view.WindowCompat
object StatusBarHelps {
fun immersiveStatusBar(activity: Activity, @ColorInt statusBarColor: Int, isDark: Boolean) {
activity.window.apply {
// 透明状态栏
addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
this.statusBarColor = statusBarColor
if (isDark) {
decorView.systemUiVisibility =
decorView.systemUiVisibility or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
} else{
decorView.systemUiVisibility =
decorView.systemUiVisibility and View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.inv()
}
}
}
fun setDark(activity: Activity, isDark: Boolean) {
activity.window.apply {
if (isDark) {
decorView.systemUiVisibility =
decorView.systemUiVisibility or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
} else {
decorView.systemUiVisibility =
decorView.systemUiVisibility and View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.inv()
}
}
}
fun immersive(activity: Activity, @ColorInt statusBarColor: Int) {
immersiveStatusBar(activity, statusBarColor, false)
}
fun immersive(activity: Activity) {
// 设置状态栏透明
activity.window.statusBarColor = Color.TRANSPARENT
WindowCompat.setDecorFitsSystemWindows(activity.window, false)
}
}
\ No newline at end of file
package com.base.pdfviewerscannerwhite.mix
import android.content.Context
import java.math.BigDecimal
import java.math.RoundingMode
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
import java.util.Locale
object Utils {
fun getFormatSize(bytes: Number): String {
val value: Double
val unit: String
if (bytes.toDouble() < 1024) {
value = bytes.toDouble()
unit = " B"
} else if (bytes.toDouble() < 1024 * 1024) {
value = bytes.toDouble() / 1024
unit = " KB"
} else if (bytes.toDouble() < 1024 * 1024 * 1024) {
value = bytes.toDouble() / (1024 * 1024)
unit = " MB"
} else {
value = bytes.toDouble() / (1024 * 1024 * 1024)
unit = " GB"
}
val formattedNumber = String.format("%.2f", value)
return formattedNumber + unit
}
fun getSize(bytes: Long): String {
if (bytes == 0.toLong()) return "0 B"
val value: Double
val unit: String
if (bytes.toDouble() < 1024) {
value = bytes.toDouble()
unit = " B"
} else if (bytes.toDouble() < 1024 * 1024) {
value = bytes.toDouble() / 1024
unit = " KB"
} else if (bytes.toDouble() < 1024 * 1024 * 1024) {
value = bytes.toDouble() / (1024 * 1024)
unit = " MB"
} else {
value = bytes.toDouble() / (1024 * 1024 * 1024)
unit = " GB"
}
val formattedNumber = String.format("%.1f", value)
return formattedNumber + unit
}
fun getSizeArray(bytes: Long): Array<String> {
val value = getSize(bytes)
val size = value.substring(0, value.indexOf(" "))
val unit = value.substring(value.indexOf(" ") + 1)
return arrayOf(size, unit)
}
fun Long.toDateString(): String {
val formatter = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
return formatter.format(Date(this))
}
fun Context.toDate(): String {
val formatter = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
return formatter.format(Date())
}
fun getCurrentMinute(): Int {
val calendar = Calendar.getInstance()
return calendar.get(Calendar.MINUTE)
}
fun calculate(dividend: Int, divisor: Int): String {
val bigDecimalDividend = BigDecimal(dividend)
val bigDecimalDivisor = BigDecimal(divisor)
// 执行除法操作,并保留一位小数,不四舍五入
val result = bigDecimalDividend.divide(bigDecimalDivisor, 1, RoundingMode.DOWN)
// 将结果转换回Double
return result.toString()
}
}
\ No newline at end of file
package com.base.pdfviewerscannerwhite.mix
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.View
import androidx.activity.addCallback
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.GridLayoutManager
import com.base.pdfviewerscannerwhite.R
import com.base.pdfviewerscannerwhite.databinding.ActivityWhatsappCleanBinding
import com.base.pdfviewerscannerwhite.mix.MineTypeHelps.TYPE_AUDIO
import com.base.pdfviewerscannerwhite.mix.MineTypeHelps.TYPE_IMAGE
import com.base.pdfviewerscannerwhite.mix.MineTypeHelps.TYPE_VIDEO
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.util.Locale
class WhatsappCleanActivity : BaseActivity2() {
companion object {
fun start(context: Context) {
val intent = Intent(context, WhatsappCleanActivity::class.java)
context.startActivity(intent)
}
}
private val binding by lazy {
ActivityWhatsappCleanBinding.inflate(layoutInflater)
}
private lateinit var videoAdapter: WhatsappCleanAdapter
private lateinit var imageAdapter: WhatsappCleanAdapter
private var videoList = listOf<FileBean>()
private var imageList = listOf<FileBean>()
private var audioList = listOf<FileBean>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
initView()
initData()
showAnimationAd(LottieType.WHATSAPP)
onBackPressedDispatcher.addCallback {
handleBackPressed(this@WhatsappCleanActivity)
}
}
private fun initView() {
videoAdapter = WhatsappCleanAdapter(TYPE_VIDEO)
binding.rvVideo.adapter = videoAdapter
binding.rvVideo.layoutManager = GridLayoutManager(this, 3, GridLayoutManager.VERTICAL, false)
imageAdapter = WhatsappCleanAdapter(TYPE_IMAGE)
binding.rvImage.adapter = imageAdapter
binding.rvImage.layoutManager = GridLayoutManager(this, 3, GridLayoutManager.VERTICAL, false)
binding.viewVideo.setOnClickListener {
toDetail(videoList, videoAdapter.type, getString(R.string.video_messages))
}
binding.viewImage.setOnClickListener {
toDetail(imageList, imageAdapter.type, getString(R.string.image_messages))
}
binding.flBack.setOnClickListener { backPressed() }
binding.clVideoMessage.setOnClickListener { toDetail(videoList, videoAdapter.type, getString(R.string.video_messages)) }
binding.clImageMessage.setOnClickListener { toDetail(imageList, imageAdapter.type, getString(R.string.image_messages)) }
binding.llAudioMessage.setOnClickListener { toDetail(audioList, TYPE_AUDIO, getString(R.string.audio_messages)) }
}
private fun initData() {
lifecycleScope.launch(Dispatchers.IO) {
val filesDeferred = async { FileHelps.findWhatsappFiles() }
val files = filesDeferred.await()
videoList = files.filter { file ->
MineTypeHelps.videos.any { suffix -> file.name.lowercase(Locale.ROOT).endsWith(suffix) }
}
imageList = files.filter { file ->
MineTypeHelps.images.any { suffix -> file.name.lowercase(Locale.ROOT).endsWith(suffix) }
}
audioList = files.filter { file ->
MineTypeHelps.audios.any { suffix -> file.name.lowercase(Locale.ROOT).endsWith(suffix) }
}
val videoSize = videoList.sumOf { it.length }
val imageSize = imageList.sumOf { it.length }
val audioSize = audioList.sumOf { it.length }
val total = videoSize + imageSize + audioSize
val value = Utils.getSizeArray(total)
withContext(Dispatchers.Main) {
binding.tvSize.text = value[0]
binding.tvUnit.text = value[1]
binding.tvVideoSize.text = Utils.getSize(videoSize)
binding.tvImageSize.text = Utils.getSize(imageSize)
binding.tvAudioSize.text = Utils.getSize(audioSize)
binding.tvNoVideo.visibility = if (videoList.isEmpty()) View.VISIBLE else View.GONE
binding.tvNoImage.visibility = if (imageList.isEmpty()) View.VISIBLE else View.GONE
val textColor = if (videoList.isEmpty()) getColor(R.color.color_aeb4bd) else getColor(R.color.color_0592ee)
binding.tvVideoSize.setTextColor(textColor)
binding.tvImageSize.setTextColor(textColor)
binding.tvAudioSize.setTextColor(textColor)
if (audioList.isNotEmpty()) {
val foundVoiceMessage = getString(R.string.found_voice_message).replace("3", "${audioList.size}")
binding.tvNoAudio.text = foundVoiceMessage
}
videoAdapter.updateData(videoList)
imageAdapter.updateData(imageList)
}
}
}
private fun toDetail(list: List<FileBean>, type: Int, title: String) {
if (list.isEmpty()) return
list.forEach { it.isSelected = false }
WhatsappCleanDetailActivity.start(this, list, type, title)
}
}
\ No newline at end of file
package com.base.pdfviewerscannerwhite.mix
import android.annotation.SuppressLint
import android.media.tv.TvTrackInfo.TYPE_VIDEO
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.base.pdfviewerscannerwhite.databinding.ItemWhatsappCleanBinding
import com.base.pdfviewerscannerwhite.mix.AppHelps.dpToPx
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.bitmap.CenterCrop
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
import com.bumptech.glide.request.RequestOptions
class WhatsappCleanAdapter(
var data: List<FileBean>,
val type: Int = TYPE_VIDEO
) : BaseAdapter<FileBean, ItemWhatsappCleanBinding>(data.take(3)) {
constructor(type: Int = TYPE_VIDEO) : this(emptyList(), type)
fun updateData(data: List<FileBean>) {
this.data = data
submitList(data.take(3))
}
override fun getViewBinding(
layoutInflater: LayoutInflater,
parent: ViewGroup
): ItemWhatsappCleanBinding {
return ItemWhatsappCleanBinding.inflate(layoutInflater, parent, false)
}
@SuppressLint("SetTextI18n")
override fun bind(
holder: BaseViewHolder<ItemWhatsappCleanBinding>,
position: Int,
item: FileBean
) {
val width = holder.itemView.context.resources.displayMetrics.widthPixels
val margin = holder.itemView.context.dpToPx(128).toInt()
val imageWidth = (width - margin) / 3
holder.binding.ivImage.layoutParams.width = imageWidth
holder.binding.ivImage.layoutParams.height = imageWidth
val round = holder.itemView.context.dpToPx(8).toInt()
val options = RequestOptions().transform(CenterCrop(), RoundedCorners(round))
Glide.with(holder.itemView.context)
.load(item.path)
.apply(options)
.into(holder.binding.ivImage)
holder.binding.tvSize.text = ""
holder.binding.ivVideo.visibility = if (type == TYPE_VIDEO) View.VISIBLE else View.GONE
if (data.size > 3 && position == itemCount - 1) {
holder.binding.tvSize.text = "+${data.size - itemCount}"
} else {
holder.binding.ivShadow.visibility = View.GONE
}
}
}
\ No newline at end of file
package com.base.pdfviewerscannerwhite.mix
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.View
import androidx.activity.addCallback
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import com.base.pdfviewerscannerwhite.R
import com.base.pdfviewerscannerwhite.databinding.ActivityWhatsappCleanDetailBinding
class WhatsappCleanDetailActivity : BaseActivity2() {
companion object {
var list = listOf<FileBean>()
var type = 0
var titleName = ""
fun start(context: Context, list: List<FileBean>, type: Int, titleName: String) {
Companion.list = list
Companion.type = type
Companion.titleName = titleName
val intent = Intent(context, WhatsappCleanDetailActivity::class.java)
context.startActivity(intent)
}
}
private val binding by lazy {
ActivityWhatsappCleanDetailBinding.inflate(layoutInflater)
}
private lateinit var adapter: CleanDetailAdapter
private var total: Long = 0
private var isSelectAll = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
initView()
onBackPressedDispatcher.addCallback {
handleBackPressed(this@WhatsappCleanDetailActivity)
}
}
private fun initView() {
adapter = CleanDetailAdapter(list, type)
adapter.callback = object : BaseAdapter.OnClickCallback<FileBean> {
override fun onClicked(view: View, position: Int, item: FileBean) {
if (item.isSelected) total += item.length
else total -= item.length
isSelectAll = adapter.list.stream().allMatch(FileBean::isSelected)
updateView(total > 0)
}
}
binding.rvWhatsapp.adapter = adapter
binding.rvWhatsapp.layoutManager = if (type == 2) {
LinearLayoutManager(this)
} else {
GridLayoutManager(this, 3, GridLayoutManager.VERTICAL, false)
}
if (titleName.isNotEmpty()) binding.tvTitle.text = titleName
binding.flBack.setOnClickListener { backPressed() }
binding.llSelectAll.setOnClickListener {
isSelectAll = !isSelectAll
val list = adapter.list
list.forEach { it.isSelected = isSelectAll }
adapter.submitList(list)
total = list.filter { it.isSelected }.sumOf { it.length }
updateView(isSelectAll)
}
binding.tvDelete.setOnClickListener {
if (total <= 0) return@setOnClickListener
DialogHelps.showDeleteDialog(this, binding.tvDelete) {
showAnimationAd {
}
cleanFiles(adapter.list)
}
}
}
private fun updateView(isSelection: Boolean) {
binding.ivSelectAll.setImageResource(if (isSelectAll) R.mipmap.ic_check_s else R.mipmap.ic_check_n)
binding.tvDelete.setBackgroundResource(if (isSelection) R.drawable.gradient_26 else R.drawable.btn_not_clickable)
val value = Utils.getSizeArray(total)
binding.tvSize.text = value[0]
binding.tvUnit.text = value[1]
}
}
\ No newline at end of file
package com.base.pdfviewerscannerwhite.ui.main
import android.view.View
import androidx.recyclerview.widget.RecyclerView.ViewHolder
class CommonViewHolder(view: View) : ViewHolder(view)
\ No newline at end of file
package com.base.pdfviewerscannerwhite.ui.main
import android.content.Context
import android.view.ViewGroup
import com.base.pdfviewerscannerwhite.R
import com.base.pdfviewerscannerwhite.bean.FunctionUIBean
import com.base.pdfviewerscannerwhite.databinding.ItemFunctionBinding
import com.base.pdfviewerscannerwhite.utils.XmlEx.inflate
import com.chad.library.adapter4.BaseQuickAdapter
class FunctionAdapter : BaseQuickAdapter<FunctionUIBean, CommonViewHolder>() {
private val TAG = "FunctionAdapter"
var itemClick: ((key: String) -> Unit)? = null
override fun onBindViewHolder(holder: CommonViewHolder, position: Int, item: FunctionUIBean?) {
item ?: return
val binding = ItemFunctionBinding.bind(holder.itemView)
binding.iv.setImageResource(item.icon)
binding.tvDesc.text = item.desc
binding.root.setOnClickListener {
itemClick?.invoke(item.key)
}
}
override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): CommonViewHolder {
return CommonViewHolder(R.layout.item_function.inflate(parent))
}
}
\ No newline at end of file
......@@ -11,14 +11,31 @@ import android.os.StatFs
import android.os.storage.StorageManager
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import com.base.pdfviewerscannerwhite.R
import com.base.pdfviewerscannerwhite.bean.ConstObject.DO_LOCK_PDF
import com.base.pdfviewerscannerwhite.bean.ConstObject.DO_MERGE_PDF
import com.base.pdfviewerscannerwhite.bean.ConstObject.DO_SPLIT_PDF
import com.base.pdfviewerscannerwhite.bean.ConstObject.DO_UNLOCK_PDF
import com.base.pdfviewerscannerwhite.bean.FunctionUIBean
import com.base.pdfviewerscannerwhite.bean.FunctionUIBean.Companion.KEY_FILE_MANAGER
import com.base.pdfviewerscannerwhite.bean.FunctionUIBean.Companion.KEY_IMAGE
import com.base.pdfviewerscannerwhite.bean.FunctionUIBean.Companion.KEY_LARGE_FILE
import com.base.pdfviewerscannerwhite.bean.FunctionUIBean.Companion.KEY_LOCK
import com.base.pdfviewerscannerwhite.bean.FunctionUIBean.Companion.KEY_MERGE
import com.base.pdfviewerscannerwhite.bean.FunctionUIBean.Companion.KEY_PROCESS
import com.base.pdfviewerscannerwhite.bean.FunctionUIBean.Companion.KEY_SCAN
import com.base.pdfviewerscannerwhite.bean.FunctionUIBean.Companion.KEY_SCREENSHOT
import com.base.pdfviewerscannerwhite.bean.FunctionUIBean.Companion.KEY_SIMILAR
import com.base.pdfviewerscannerwhite.bean.FunctionUIBean.Companion.KEY_SPLIT
import com.base.pdfviewerscannerwhite.bean.FunctionUIBean.Companion.KEY_UNLOCK
import com.base.pdfviewerscannerwhite.bean.FunctionUIBean.Companion.KEY_WHATSAPP
import com.base.pdfviewerscannerwhite.databinding.FragmentToolBinding
import com.base.pdfviewerscannerwhite.helper.BaseFragment
import com.base.pdfviewerscannerwhite.helper.WeatherUtils
import com.base.pdfviewerscannerwhite.ui.appprocess.AppProcessActivity
import com.base.pdfviewerscannerwhite.mix.LargeFileCleanActivity
import com.base.pdfviewerscannerwhite.mix.ScreenshotCleanActivity
import com.base.pdfviewerscannerwhite.mix.SimilarPhotosActivity
import com.base.pdfviewerscannerwhite.mix.WhatsappCleanActivity
import com.base.pdfviewerscannerwhite.ui.appprocess.AppProcessLoadingActivity
import com.base.pdfviewerscannerwhite.ui.cleanjunk.ScanJunkActivity
import com.base.pdfviewerscannerwhite.ui.document.pdf.PdfActivity
......@@ -54,83 +71,132 @@ class ToolFragment : BaseFragment<FragmentToolBinding>() {
bean?.let {
binding.tvWendu.text = (it.tempMax.toInt() + it.tempMin.toInt() / 2).toString()
}
val adapter = FunctionAdapter()
adapter.itemClick = ::itemClick
binding.rv.adapter = adapter
adapter.submitList(
listOf(
FunctionUIBean(KEY_PROCESS, R.mipmap.process, requireContext().resources.getString(R.string.app_process)),
FunctionUIBean(KEY_FILE_MANAGER, R.mipmap.manager_tool, requireContext().resources.getString(R.string.file_manager)),
FunctionUIBean(KEY_MERGE, R.mipmap.merge_tool, requireContext().resources.getString(R.string.merge_pdf)),
FunctionUIBean(KEY_SPLIT, R.mipmap.split_tool, requireContext().resources.getString(R.string.split_pdf)),
FunctionUIBean(KEY_SCAN, R.mipmap.scan_tool, requireContext().resources.getString(R.string.scan_pdf)),
FunctionUIBean(KEY_LOCK, R.mipmap.lock_tool, requireContext().resources.getString(R.string.lock_pdf)),
FunctionUIBean(KEY_UNLOCK, R.mipmap.unlock_tool, requireContext().resources.getString(R.string.unlock_pdf)),
FunctionUIBean(KEY_IMAGE, R.mipmap.imagepdf, requireContext().resources.getString(R.string.image_pdf)),
FunctionUIBean(
KEY_SCREENSHOT,
R.mipmap.icon_screenshot_tools,
requireContext().resources.getString(R.string.screenshot_clean)
),
FunctionUIBean(KEY_SIMILAR, R.mipmap.icon_similar_tool, requireContext().resources.getString(R.string.similar_photos)),
FunctionUIBean(KEY_WHATSAPP, R.mipmap.icon_whatsapp_tools, requireContext().resources.getString(R.string.whatsapp)),
FunctionUIBean(
KEY_LARGE_FILE,
R.mipmap.icon_file_tool,
requireContext().resources.getString(R.string.large_file_clean)
)
)
)
}
override fun setListener() {
super.setListener()
binding.llManager.setOnClickListener {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
intent.addCategory(Intent.CATEGORY_OPENABLE)
intent.setType("application/pdf")
intent.flags = Intent.FLAG_GRANT_WRITE_URI_PERMISSION
(requireActivity() as MainActivity).launcher.launch(intent) {
val uri = it.data?.data ?: return@launch
private fun itemClick(key: String) {
when (key) {
KEY_PROCESS -> {
startActivity(Intent(requireContext(), AppProcessLoadingActivity::class.java))
}
lifecycleScope.launch(Dispatchers.IO) {
val state = PdfBoxUtils.checkPdfEncryption(uri = uri.toString())
if (state == 0) {
launch(Dispatchers.Main) {
startActivity(Intent(requireContext(), PdfActivity::class.java).apply {
putExtra("uri", uri.toString())
})
}
} else {
launch(Dispatchers.Main) {
requireContext().showPdfPwdDialog(
state = state,
uri = uri.toString(),
isCheckPwd = true,
verificationAction = { pwd ->
startActivity(Intent(requireContext(), PdfActivity::class.java).apply {
putExtra("uri", uri.toString())
putExtra("pwd", pwd)
})
KEY_FILE_MANAGER -> {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
intent.addCategory(Intent.CATEGORY_OPENABLE)
intent.setType("application/pdf")
intent.flags = Intent.FLAG_GRANT_WRITE_URI_PERMISSION
(requireActivity() as MainActivity).launcher.launch(intent) {
val uri = it.data?.data ?: return@launch
lifecycleScope.launch(Dispatchers.IO) {
val state = PdfBoxUtils.checkPdfEncryption(uri = uri.toString())
if (state == 0) {
launch(Dispatchers.Main) {
startActivity(Intent(requireContext(), PdfActivity::class.java).apply {
putExtra("uri", uri.toString())
})
}
} else {
launch(Dispatchers.Main) {
requireContext().showPdfPwdDialog(
state = state,
uri = uri.toString(),
isCheckPwd = true,
verificationAction = { pwd ->
startActivity(Intent(requireContext(), PdfActivity::class.java).apply {
putExtra("uri", uri.toString())
putExtra("pwd", pwd)
})
})
}
}
}
}
}
KEY_MERGE -> {
startActivity(Intent(requireContext(), PdfSelectActivity::class.java).apply {
putExtra("doWhat", DO_MERGE_PDF)
})
}
KEY_SPLIT -> {
startActivity(Intent(requireContext(), PdfSelectActivity::class.java).apply {
putExtra("doWhat", DO_SPLIT_PDF)
})
}
KEY_SCAN, KEY_IMAGE -> {
val mainActivity = (requireActivity() as MainActivity?)
mainActivity ?: return
mainActivity.useGmsScanFunction()
}
KEY_LOCK -> {
startActivity(Intent(requireContext(), PdfSelectActivity::class.java).apply {
putExtra("doWhat", DO_LOCK_PDF)
})
}
KEY_UNLOCK -> {
startActivity(Intent(requireContext(), PdfSelectActivity::class.java).apply {
putExtra("doWhat", DO_UNLOCK_PDF)
})
}
KEY_SCREENSHOT -> {
startActivity(Intent(requireContext(), ScreenshotCleanActivity::class.java))
}
KEY_SIMILAR -> {
startActivity(Intent(requireContext(), SimilarPhotosActivity::class.java))
}
KEY_WHATSAPP -> {
startActivity(Intent(requireContext(), WhatsappCleanActivity::class.java))
}
KEY_LARGE_FILE -> {
startActivity(Intent(requireContext(), LargeFileCleanActivity::class.java))
}
}
binding.llMerge.setOnClickListener {
startActivity(Intent(requireContext(), PdfSelectActivity::class.java).apply {
putExtra("doWhat", DO_MERGE_PDF)
})
}
binding.llSplit.setOnClickListener {
startActivity(Intent(requireContext(), PdfSelectActivity::class.java).apply {
putExtra("doWhat", DO_SPLIT_PDF)
})
}
binding.llLock.setOnClickListener {
startActivity(Intent(requireContext(), PdfSelectActivity::class.java).apply {
putExtra("doWhat", DO_LOCK_PDF)
})
}
binding.llUnlock.setOnClickListener {
startActivity(Intent(requireContext(), PdfSelectActivity::class.java).apply {
putExtra("doWhat", DO_UNLOCK_PDF)
})
}
}
override fun setListener() {
super.setListener()
binding.llSet.setOnClickListener {
startActivity(Intent(requireContext(), SetActivity::class.java))
}
binding.llImagePdf.setOnClickListener {
val mainActivity = (requireActivity() as MainActivity?)
mainActivity ?: return@setOnClickListener
mainActivity.useGmsScanFunction()
}
binding.llScan.setOnClickListener {
val mainActivity = (requireActivity() as MainActivity?)
mainActivity ?: return@setOnClickListener
mainActivity.useGmsScanFunction()
}
binding.llProcess.setOnClickListener {
startActivity(Intent(requireContext(), AppProcessLoadingActivity::class.java))
}
binding.tvClean.setOnClickListener {
startActivity(Intent(requireContext(), ScanJunkActivity::class.java))
}
......
......@@ -8,8 +8,10 @@ import com.base.pdfviewerscannerwhite.R
import com.base.pdfviewerscannerwhite.ads.admob.AdmobNativeUtils
import com.base.pdfviewerscannerwhite.bean.ConstObject.FUNCTION_APP_PROCESS
import com.base.pdfviewerscannerwhite.bean.ConstObject.FUNCTION_SCAM_JUNK
import com.base.pdfviewerscannerwhite.bean.ConstObject.FUNCTION_SCREEN_SHORT
import com.base.pdfviewerscannerwhite.databinding.ActivityResultBinding
import com.base.pdfviewerscannerwhite.helper.BaseActivity
import com.base.pdfviewerscannerwhite.mix.LargeFileCleanActivity
import com.base.pdfviewerscannerwhite.ui.appprocess.AppProcessLoadingActivity
import com.base.pdfviewerscannerwhite.ui.cleanjunk.ScanJunkActivity
import com.base.pdfviewerscannerwhite.utils.BarUtils
......@@ -60,6 +62,24 @@ class ResultActivity : BaseActivity<ActivityResultBinding>() {
binding.tvSize.text = "Cleaned up ${s.toFormatSize(1)}"
}
}
FUNCTION_SCREEN_SHORT -> {
binding.tvTitle.text = getString(R.string.screenshot_clean)
val s = intent.extras?.getLong("clean_size") ?: 0L
if (s != 0L) {
binding.tvSize.text = "Cleaned up ${s.toFormatSize(1)}"
}
binding.tvFunction.text = getString(R.string.large_file_clean)
binding.ivFunction.setImageResource(R.mipmap.icon_file_tool)
binding.tvFunctionDesc.text = getString(R.string.find_your_large_file_to_clean_it)
binding.tvFunctionBtn.text = getString(R.string.scan_now)
binding.tvFunctionBtn.setOnClickListener {
startActivity(Intent(this, LargeFileCleanActivity::class.java))
finish()
}
}
}
......
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#2372FC" android:state_checked="true" />
<item android:color="#D7DBE4" android:state_checked="false" />
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/color_f0f0f0" />
<corners android:radius="16dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<!-- <solid android:color="#EDFF7A" />-->
<size
android:width="25dp"
android:height="25dp" />
<!-- 边缘全透明 -->
<stroke
android:width="8dp"
android:color="#00000000" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<!-- <solid android:color="#2372FD" />-->
<size android:height="25dp" />
<corners android:radius="30dp" />
</shape>
</item>
</layer-list>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FFC9C9C9" />
<corners android:radius="26dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="4dp" />
<solid android:color="@color/white" />
<stroke android:width="1dp" android:color="@color/color_aeb4bd" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="@color/color_8eb0ff"
android:endColor="@color/color_6473f8"
android:angle="0"
android:centerX="0.5"
android:centerY="0.5" />
<corners android:radius="37dp" />
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="@color/color_ff6400"
android:endColor="@color/color_ff8200"
android:angle="0"
android:centerX="0.5"
android:centerY="0.5" />
<corners android:radius="37dp" />
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:startColor="@color/color_ff6400"
android:endColor="@color/color_ff8200"
android:angle="0"
android:centerX="0.5"
android:centerY="0.5" />
<corners android:radius="4dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:startColor="@color/color_8eb0ff"
android:endColor="@color/color_6473f8"
android:angle="270"
android:centerX="0.5"
android:centerY="0.5" />
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:startColor="#EBEDFF"
android:endColor="#EBEDFF"
android:angle="0"
android:centerX="0.5"
android:centerY="0.5" />
<corners android:radius="50dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="37dp" />
<solid android:color="@android:color/transparent" />
<stroke android:width="1dp" android:color="@color/color_ebebeb" />
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/color_66000000" />
<corners
android:bottomLeftRadius="8dp"
android:bottomRightRadius="8dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/color_66000000" />
<corners android:radius="8dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/white" />
<corners android:radius="12dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/white" />
<corners android:radius="16dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/white" />
<corners
android:bottomLeftRadius="15dp"
android:bottomRightRadius="15dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/white" />
<corners
android:topLeftRadius="15dp"
android:topRightRadius="15dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/color_f7fafa">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_top"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/gradient_background"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/ll_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingTop="6dp"
android:paddingBottom="6dp"
app:layout_constraintTop_toTopOf="parent">
<FrameLayout
android:id="@+id/fl_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="11dp"
android:padding="4dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/icon_return_bar_nor" />
</FrameLayout>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/large_file_clean"
android:textColor="@color/white"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@id/fl_back"
app:layout_constraintStart_toEndOf="@id/fl_back"
app:layout_constraintTop_toTopOf="@id/fl_back" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/ll_tab"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="12dp"
android:paddingTop="24dp"
app:layout_constraintTop_toBottomOf="@id/cl_top">
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/ll_type"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@drawable/large_file_tab"
android:gravity="center"
android:orientation="horizontal"
android:paddingVertical="8dp">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/icon_all_n" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="2dp"
android:layout_marginEnd="2dp"
android:text="@string/all_types"
android:textColor="@color/color_181b1f"
android:textSize="14sp"
android:textStyle="bold" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_type_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/icon_jiantou_down_small" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/ll_size"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="6dp"
android:layout_weight="1"
android:background="@drawable/large_file_tab"
android:gravity="center"
android:orientation="horizontal"
android:paddingHorizontal="10dp"
android:paddingVertical="8dp">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/icon_mb_n" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="2dp"
android:layout_marginEnd="2dp"
android:text="@string/mb_10"
android:textColor="@color/color_181b1f"
android:textSize="14sp"
android:textStyle="bold" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_size_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/icon_jiantou_down_small" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/ll_time"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@drawable/large_file_tab"
android:gravity="center"
android:orientation="horizontal"
android:paddingHorizontal="10dp"
android:paddingVertical="8dp">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/icon_time_n" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="2dp"
android:layout_marginEnd="2dp"
android:text="@string/all_time"
android:textColor="@color/color_181b1f"
android:textSize="14sp"
android:textStyle="bold" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_time_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/icon_jiantou_down_small" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
<com.base.pdfviewerscannerwhite.mix.NativeView
android:id="@+id/ad_native"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="10dp"
android:layout_marginTop="10dp"
android:visibility="gone"
app:layout_constraintTop_toBottomOf="@id/ll_tab" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/kongzhuangtai"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_large_file"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginBottom="12dp"
android:paddingVertical="6dp"
android:scrollbars="none"
app:layout_constraintBottom_toTopOf="@id/tv_delete"
app:layout_constraintTop_toBottomOf="@id/ad_native" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_delete"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="30dp"
android:layout_marginEnd="30dp"
android:layout_marginBottom="40dp"
android:background="@drawable/gradient_not_clickable"
android:paddingTop="12dp"
android:paddingBottom="12dp"
android:text="@string/delete"
android:textAlignment="center"
android:textColor="@color/white"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_tab"
android:layout_width="match_parent"
android:layout_height="0dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/ll_tab">
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:alpha="0.2"
android:src="@color/black" />
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/white_background_bottom"
android:orientation="vertical"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_other_than"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:paddingTop="8dp"
android:text="@string/other_than"
android:textColor="@color/color_aeb4bd"
android:textSize="12sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_tab"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="12dp"
android:scrollbars="none"
app:layout_constraintTop_toBottomOf="@id/tv_other_than" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.constraintlayout.widget.ConstraintLayout>
<include
android:id="@+id/animation"
layout="@layout/custom_animation"
android:visibility="gone" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
......@@ -26,6 +26,7 @@
</FrameLayout>
<TextView
android:id="@+id/tvTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:includeFontPadding="false"
......
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/color_f7fafa">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_top"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/gradient_background"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/ll_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingTop="6dp"
android:paddingBottom="6dp"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="@+id/fl_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="11dp"
android:importantForAccessibility="no"
android:padding="4dp"
android:src="@mipmap/icon_return_bar_nor"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/screenshot_clean"
android:textColor="@color/white"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@id/fl_back"
app:layout_constraintStart_toEndOf="@id/fl_back"
app:layout_constraintTop_toTopOf="@id/fl_back" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="34dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/ll_title">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0"
android:textColor="@color/white"
android:textSize="32sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_unit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="KB"
android:textColor="@color/white"
android:textSize="12sp"
app:layout_constraintStart_toEndOf="@id/tv_size"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginBottom="60dp"
android:text="@string/screenshots_totally"
android:textColor="@color/white"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/cl_size" />
<View
android:layout_width="match_parent"
android:layout_height="10dp"
android:layout_marginTop="9dp"
android:background="@drawable/white_background_top"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<pokercc.android.expandablerecyclerview.ExpandableRecyclerView
android:id="@+id/expandable_files"
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="@color/white"
android:paddingBottom="12dp"
app:layout_constraintBottom_toTopOf="@id/ll_bottom"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/cl_top" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_empty"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/ll_bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:gravity="center"
android:orientation="horizontal"
android:padding="16dp"
app:layout_constraintBottom_toBottomOf="parent">
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/ll_select_all"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_select_all"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_check_n" />
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:text="@string/select_all"
android:textColor="@color/color_666666"
android:textSize="12sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_delete"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_weight="1"
android:background="@drawable/btn_not_clickable"
android:gravity="center"
android:paddingVertical="10dp"
android:text="@string/delete"
android:textColor="@color/white"
android:textSize="18sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
<include
android:id="@+id/animation"
layout="@layout/custom_animation" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/color_f7fafa">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_top"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/gradient_background"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/ll_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingTop="6dp"
android:paddingBottom="6dp"
app:layout_constraintTop_toTopOf="parent">
<FrameLayout
android:id="@+id/fl_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="11dp"
android:padding="4dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/icon_return_bar_nor" />
</FrameLayout>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/similar_photos"
android:textColor="@color/white"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@id/fl_back"
app:layout_constraintStart_toEndOf="@id/fl_back"
app:layout_constraintTop_toTopOf="@id/fl_back" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_select"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
app:layout_constraintTop_toBottomOf="@id/cl_top">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginVertical="13dp"
android:layout_marginStart="15dp"
android:text="@string/auto_select"
android:textColor="@color/black"
android:textSize="18sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/iv_select"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="10dp"
android:thumb="@drawable/bg_switch_thumb_ffffff"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:thumbTint="@color/white"
app:track="@drawable/bg_switch_track"
app:trackTint="@color/switch_track_selector" />
</androidx.constraintlayout.widget.ConstraintLayout>
<com.base.pdfviewerscannerwhite.mix.NativeView
android:id="@+id/ad_native"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="15dp"
android:layout_marginTop="10dp"
android:visibility="gone"
app:layout_constraintTop_toBottomOf="@id/cl_select" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_photo"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginBottom="20dp"
android:scrollbars="none"
app:layout_constraintBottom_toTopOf="@id/tv_delete"
app:layout_constraintTop_toBottomOf="@id/ad_native" />
<TextView
android:id="@+id/tv_delete"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="30dp"
android:layout_marginBottom="55dp"
android:background="@drawable/gradient_not_clickable"
android:gravity="center"
android:paddingVertical="12dp"
android:text="@string/delete"
android:textColor="@color/white"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent" />
<include
android:id="@+id/animation"
layout="@layout/custom_animation"
android:visibility="gone" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/color_f7fafa">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_top"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/gradient_background"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/ll_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingTop="6dp"
android:paddingBottom="6dp"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="@+id/fl_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="11dp"
android:importantForAccessibility="no"
android:padding="4dp"
android:src="@mipmap/icon_return_bar_nor"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/whatsapp_clean"
android:textColor="@color/white"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@id/fl_back"
app:layout_constraintStart_toEndOf="@id/fl_back"
app:layout_constraintTop_toTopOf="@id/fl_back" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="34dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/ll_title">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0"
android:textColor="@color/white"
android:textSize="32sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_unit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="B"
android:textColor="@color/white"
android:textSize="12sp"
app:layout_constraintStart_toEndOf="@id/tv_size"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginBottom="67dp"
android:text="@string/cleanable"
android:textColor="@color/white"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/cl_size" />
<View
android:layout_width="match_parent"
android:layout_height="10dp"
android:layout_marginTop="9dp"
android:background="@drawable/white_background_top"
android:backgroundTint="@color/color_f7fafa"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_video_message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginEnd="15dp"
android:background="@drawable/white_background"
android:gravity="center"
android:orientation="vertical"
android:paddingStart="16dp"
android:paddingTop="12dp"
android:paddingEnd="16dp"
android:paddingBottom="12dp"
app:layout_constraintTop_toBottomOf="@id/cl_top">
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/ll_video"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/icon_video_junk_nor" />
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_weight="1"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/video_messages"
android:textColor="@color/color_181b1f"
android:textSize="16sp"
android:textStyle="bold" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_no_video"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:text="@string/no_video_message_found"
android:textColor="@color/color_aeb4bd"
android:textSize="12sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_video_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="4dp"
android:text="0KB"
android:textColor="@color/color_6473f8"
android:textSize="12sp" />
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/icon_jiantou" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_video"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="48dp"
android:scrollbars="none"
app:layout_constraintTop_toBottomOf="@id/ll_video" />
<View
android:id="@+id/view_video"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="@id/rv_video"
app:layout_constraintEnd_toEndOf="@id/rv_video"
app:layout_constraintStart_toStartOf="@id/rv_video"
app:layout_constraintTop_toTopOf="@id/rv_video" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_image_message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="15dp"
android:background="@drawable/white_background"
android:gravity="center"
android:orientation="vertical"
android:paddingStart="16dp"
android:paddingTop="12dp"
android:paddingEnd="16dp"
android:paddingBottom="12dp"
app:layout_constraintTop_toBottomOf="@id/cl_video_message">
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/ll_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/icon_image_junk_nor" />
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_weight="1"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/image_messages"
android:textColor="@color/color_181b1f"
android:textSize="16sp"
android:textStyle="bold" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_no_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:text="@string/no_image_message_found"
android:textColor="@color/color_aeb4bd"
android:textSize="12sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_image_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="4dp"
android:text="0KB"
android:textColor="@color/color_6473f8"
android:textSize="12sp" />
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/icon_jiantou" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="48dp"
android:scrollbars="none"
app:layout_constraintTop_toBottomOf="@id/ll_image" />
<View
android:id="@+id/view_image"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="@id/rv_image"
app:layout_constraintEnd_toEndOf="@id/rv_image"
app:layout_constraintStart_toStartOf="@id/rv_image"
app:layout_constraintTop_toTopOf="@id/rv_image" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/ll_audio_message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="15dp"
android:background="@drawable/white_background"
android:gravity="center"
android:orientation="horizontal"
android:paddingStart="16dp"
android:paddingTop="12dp"
android:paddingEnd="16dp"
android:paddingBottom="12dp"
app:layout_constraintTop_toBottomOf="@id/cl_image_message">
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/icon_audio_junk_nor" />
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:layout_weight="1"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/audio_messages"
android:textColor="@color/color_181b1f"
android:textSize="16sp"
android:textStyle="bold" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_no_audio"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:text="@string/no_audio_message_found"
android:textColor="@color/color_aeb4bd"
android:textSize="12sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_audio_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="4dp"
android:text="0KB"
android:textColor="@color/color_6473f8"
android:textSize="12sp" />
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/icon_jiantou" />
</androidx.appcompat.widget.LinearLayoutCompat>
<include
android:id="@+id/animation"
layout="@layout/custom_animation"
android:visibility="gone" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/color_f7fafa">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_top"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/gradient_background"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/ll_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="6dp"
android:paddingBottom="6dp"
android:gravity="center_vertical"
android:orientation="horizontal"
app:layout_constraintTop_toTopOf="parent">
<FrameLayout
android:id="@+id/fl_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="11dp"
android:padding="4dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent">
<androidx.appcompat.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/icon_return_bar_nor" />
</FrameLayout>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/whatsapp_clean"
android:textColor="@color/white"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintTop_toTopOf="@id/fl_back"
app:layout_constraintBottom_toBottomOf="@id/fl_back"
app:layout_constraintStart_toEndOf="@id/fl_back" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="34dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/ll_title">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0"
android:textColor="@color/white"
android:textSize="32sp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_unit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="KB"
android:textColor="@color/white"
android:textSize="12sp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toEndOf="@id/tv_size" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginBottom="67dp"
android:text="@string/selected"
android:textColor="@color/white"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/cl_size" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_whatsapp"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="16dp"
android:paddingBottom="8dp"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:scrollbars="none"
app:layout_constraintTop_toBottomOf="@id/cl_top"
app:layout_constraintBottom_toTopOf="@id/ll_bottom" />
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/ll_bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp"
android:gravity="center"
android:background="@color/white"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent">
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/ll_select_all"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_select_all"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_check_n" />
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:text="@string/select_all"
android:textColor="@color/color_666666"
android:textSize="12sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_delete"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginStart="16dp"
android:paddingVertical="10dp"
android:gravity="center"
android:background="@drawable/btn_not_clickable"
android:text="@string/delete"
android:textColor="@color/white"
android:textSize="18sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
<include
android:id="@+id/animation"
android:visibility="gone"
layout="@layout/custom_animation" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/gradient_background">
<androidx.constraintlayout.widget.Guideline
android:id="@+id/gl_line"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0" />
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/lottie_animation"
android:layout_width="wrap_content"
android:layout_height="290dp"
android:layout_marginTop="50dp"
android:adjustViewBounds="true"
app:lottie_loop="true"
app:lottie_autoPlay="true"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/gl_line" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_progress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingVertical="2dp"
android:gravity="center"
android:text="0%"
android:textAlignment="center"
android:textColor="@color/white"
android:textSize="30sp"
android:textStyle="bold"
app:layout_constraintTop_toBottomOf="@id/lottie_animation" />
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/please_wait"
android:textAlignment="center"
android:textColor="@color/white"
android:textSize="14sp"
app:layout_constraintTop_toBottomOf="@id/tv_progress" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/white_background">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:layout_marginStart="24dp"
android:layout_marginEnd="24dp"
android:includeFontPadding="false"
android:lineSpacingExtra="4dp"
android:text="@string/delete_title"
android:textAlignment="center"
android:textColor="@color/color_181b1f"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginStart="24dp"
android:layout_marginEnd="24dp"
android:lineSpacingExtra="4dp"
android:includeFontPadding="false"
android:text="@string/delete_content"
android:textAlignment="center"
android:textColor="@color/color_666666"
android:textSize="16sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_title" />
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginBottom="24dp"
android:paddingStart="32dp"
android:paddingEnd="32dp"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_content">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_cancel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginEnd="8dp"
android:paddingVertical="8dp"
android:gravity="center"
android:background="@drawable/button_border_background"
android:text="@string/cancel"
android:textColor="@color/color_aeb4bd"
android:textSize="14sp" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_delete"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginStart="8dp"
android:paddingVertical="8dp"
android:gravity="center"
android:background="@drawable/gradient_4"
android:text="@string/delete"
android:textColor="@color/white"
android:textSize="14sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_exit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/white_background_16"
android:paddingBottom="30dp"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginEnd="20dp"
android:src="@mipmap/icon_close_pingfen"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="48dp"
android:layout_marginTop="30dp"
android:layout_marginEnd="48dp"
android:includeFontPadding="false"
android:lineSpacingExtra="4dp"
android:text="@string/app_name"
android:textAlignment="center"
android:textColor="@color/color_181b1f"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="6dp"
android:layout_marginEnd="24dp"
android:includeFontPadding="false"
android:lineSpacingExtra="4dp"
android:text="@string/storage_permission_content"
android:textAlignment="center"
android:textColor="@color/color_666666"
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_title" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_cancel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="8dp"
android:background="@drawable/gradient_not_clickable"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:text="@string/cancel"
android:textAlignment="center"
android:textColor="@color/black"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintEnd_toStartOf="@id/tv_sure"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_content" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_sure"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="32dp"
android:background="@drawable/gradient"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:text="@string/sure"
android:textAlignment="center"
android:textColor="@color/white"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/tv_cancel"
app:layout_constraintTop_toBottomOf="@id/tv_content" />
</androidx.constraintlayout.widget.ConstraintLayout>
<com.base.pdfviewerscannerwhite.mix.NativeView
android:id="@+id/ad_native"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:background="@drawable/white_background_16"
android:padding="11dp"
android:visibility="gone"
app:layout_constraintTop_toBottomOf="@id/cl_exit" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
......@@ -298,313 +298,70 @@
</androidx.cardview.widget.CardView>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_1"
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp">
<!--文件管理-->
<LinearLayout
android:id="@+id/ll_manager"
android:layout_width="110dp"
android:layout_height="86dp"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="UseCompoundDrawables">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="12dp"
android:src="@mipmap/manager_tool"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp"
android:includeFontPadding="false"
android:text="@string/file_manager"
android:textColor="#333333"
android:textSize="14sp"
tools:ignore="HardcodedText" />
</LinearLayout>
<!--扫描-->
<LinearLayout
android:id="@+id/ll_scan"
android:layout_width="110dp"
android:layout_height="86dp"
android:layout_marginTop="8dp"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/ll_manager"
tools:ignore="UseCompoundDrawables">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="12dp"
android:src="@mipmap/scan_tool"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp"
android:includeFontPadding="false"
android:text="@string/scan_pdf"
android:textColor="#333333"
android:textSize="14sp"
tools:ignore="HardcodedText" />
</LinearLayout>
<!--图片pdf -->
<LinearLayout
android:id="@+id/ll_image_pdf"
android:layout_width="110dp"
android:layout_height="86dp"
android:layout_marginTop="8dp"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="@id/ll_manager"
app:layout_constraintStart_toStartOf="@id/ll_manager"
app:layout_constraintTop_toBottomOf="@id/ll_scan"
tools:ignore="UseCompoundDrawables">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="12dp"
android:src="@mipmap/imagepdf"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp"
android:includeFontPadding="false"
android:text="@string/image_pdf"
android:textColor="#333333"
android:textSize="14sp"
tools:ignore="HardcodedText" />
</LinearLayout>
<!-- 进程-->
<LinearLayout
android:id="@+id/ll_process"
android:layout_width="110dp"
android:layout_height="86dp"
android:layout_marginEnd="16dp"
android:orientation="vertical"
app:layout_constraintEnd_toStartOf="@+id/ll_manager"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="UseCompoundDrawables">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="12dp"
android:src="@mipmap/process"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp"
android:includeFontPadding="false"
android:text="@string/process"
android:textColor="#333333"
android:textSize="14sp"
tools:ignore="HardcodedText" />
</LinearLayout>
<!--拆分-->
<LinearLayout
android:id="@+id/ll_split"
android:layout_width="110dp"
android:layout_height="86dp"
android:layout_marginEnd="16dp"
android:orientation="vertical"
app:layout_constraintEnd_toStartOf="@id/ll_scan"
app:layout_constraintTop_toTopOf="@id/ll_scan"
tools:ignore="UseCompoundDrawables">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="12dp"
android:src="@mipmap/split_tool"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp"
android:includeFontPadding="false"
android:text="@string/split_pdf"
android:textColor="#333333"
android:textSize="14sp"
tools:ignore="HardcodedText" />
android:layout_height="wrap_content">
</LinearLayout>
<!-- 加锁-->
<LinearLayout
android:id="@+id/ll_lock"
android:layout_width="110dp"
android:layout_height="86dp"
android:layout_marginStart="16dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintStart_toEndOf="@id/ll_scan"
app:layout_constraintTop_toTopOf="@id/ll_scan"
tools:ignore="UseCompoundDrawables">
tools:ignore="UselessLeaf">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="12dp"
android:src="@mipmap/lock_tool"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp"
android:includeFontPadding="false"
android:text="@string/lock_pdf"
android:textColor="#333333"
android:textSize="14sp"
tools:ignore="HardcodedText" />
android:overScrollMode="never"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:spanCount="3"
tools:listitem="@layout/item_function">
</LinearLayout>
<!-- 合并-->
<LinearLayout
android:id="@+id/ll_merge"
android:layout_width="110dp"
android:layout_height="86dp"
android:layout_marginStart="16dp"
android:orientation="vertical"
app:layout_constraintStart_toEndOf="@id/ll_manager"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="UseCompoundDrawables">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="12dp"
android:src="@mipmap/merge_tool"
tools:ignore="ContentDescription" />
</androidx.recyclerview.widget.RecyclerView>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp"
android:includeFontPadding="false"
android:text="@string/merge_pdf"
android:textColor="#333333"
android:textSize="14sp"
tools:ignore="HardcodedText" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_set"
android:layout_width="match_parent"
android:layout_height="61dp"
android:layout_marginHorizontal="15dp"
android:layout_marginTop="40dp"
android:background="@drawable/bg_fbfbfb_15">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="15dp"
android:src="@mipmap/set"
tools:ignore="ContentDescription" />
<!--解锁-->
<LinearLayout
android:id="@+id/ll_unlock"
android:layout_width="110dp"
android:layout_height="86dp"
android:layout_marginEnd="16dp"
android:orientation="vertical"
app:layout_constraintEnd_toStartOf="@id/ll_image_pdf"
app:layout_constraintTop_toTopOf="@id/ll_image_pdf"
tools:ignore="UseCompoundDrawables">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="10dp"
android:layout_weight="1"
android:includeFontPadding="false"
android:text="@string/set"
android:textSize="16sp"
android:textStyle="bold"
tools:ignore="HardcodedText" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="12dp"
android:src="@mipmap/unlock_tool"
tools:ignore="ContentDescription" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="24dp"
android:src="@mipmap/jianotou"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp"
android:includeFontPadding="false"
android:text="@string/unlock_pdf"
android:textColor="#333333"
android:textSize="14sp"
tools:ignore="HardcodedText" />
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<LinearLayout
android:id="@+id/ll_set"
android:layout_width="match_parent"
android:layout_height="61dp"
android:layout_marginHorizontal="15dp"
android:layout_marginTop="40dp"
android:background="@drawable/bg_fbfbfb_15">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="15dp"
android:src="@mipmap/set"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="10dp"
android:layout_weight="1"
android:includeFontPadding="false"
android:text="@string/set"
android:textSize="16sp"
android:textStyle="bold"
tools:ignore="HardcodedText" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="24dp"
android:src="@mipmap/jianotou"
tools:ignore="ContentDescription" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/white">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_image"
android:layout_width="110dp"
android:layout_height="110dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_select"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:src="@mipmap/ic_check_n_photo"
app:layout_constraintTop_toTopOf="@id/iv_image"
app:layout_constraintEnd_toEndOf="parent" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_size"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:paddingTop="4dp"
android:paddingBottom="4dp"
android:gravity="center"
android:background="@drawable/shadow_background"
android:text="12.5MB"
android:textColor="@color/white"
android:textSize="14sp"
app:layout_constraintStart_toStartOf="@id/iv_image"
app:layout_constraintEnd_toEndOf="@id/iv_image"
app:layout_constraintBottom_toBottomOf="@id/iv_image" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_video_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_image"
android:layout_width="110dp"
android:layout_height="110dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_select"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:src="@mipmap/ic_check_n_photo"
app:layout_constraintTop_toTopOf="@id/iv_image"
app:layout_constraintEnd_toEndOf="parent" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_video"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/icon_play_whatsapp"
app:layout_constraintTop_toTopOf="@id/iv_image"
app:layout_constraintBottom_toBottomOf="@id/iv_image"
app:layout_constraintStart_toStartOf="@id/iv_image"
app:layout_constraintEnd_toEndOf="@id/iv_image" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_size"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:paddingTop="4dp"
android:paddingBottom="4dp"
android:gravity="center"
android:background="@drawable/shadow_background"
android:text="12.5MB"
android:textColor="@color/white"
android:textSize="14sp"
app:layout_constraintStart_toStartOf="@id/iv_image"
app:layout_constraintEnd_toEndOf="@id/iv_image"
app:layout_constraintBottom_toBottomOf="@id/iv_image" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_audio"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_audio"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/icon_audio_junk_nor"
app:layout_constraintTop_toTopOf="@id/ll_audio"
app:layout_constraintBottom_toBottomOf="@id/ll_audio"
app:layout_constraintStart_toStartOf="parent" />
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/ll_audio"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:orientation="vertical"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toEndOf="@id/iv_audio"
app:layout_constraintEnd_toStartOf="@id/iv_audio_select">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_audio_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:ellipsize="end"
android:text="@string/app_name"
android:textColor="@color/color_181b1f"
android:textSize="16sp" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_audio_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:text="@string/app_name"
android:textColor="@color/color_aeb4bd"
android:textSize="12sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_audio_select"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_check_n_photo"
app:layout_constraintTop_toTopOf="@id/ll_audio"
app:layout_constraintBottom_toBottomOf="@id/ll_audio"
app:layout_constraintEnd_toEndOf="parent" />
<View
android:id="@+id/view_line"
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:layout_marginTop="12dp"
android:background="@color/color_ebebeb"
app:layout_constraintTop_toBottomOf="@id/iv_audio" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="96dp"
android:orientation="vertical"
tools:ignore="UseCompoundDrawables">
<ImageView
android:id="@+id/iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="12dp"
android:src="@mipmap/unlock_tool"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/tvDesc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="10dp"
android:gravity="center"
android:includeFontPadding="false"
android:text="@string/unlock_pdf"
android:textColor="#333333"
android:textSize="14sp"
tools:ignore="HardcodedText" />
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white">
<View
android:id="@+id/view_bg"
android:layout_width="match_parent"
android:layout_height="12dp"
android:layout_marginTop="8dp"
android:background="@color/color_f7fafa"
app:layout_constraintTop_toTopOf="parent"/>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginVertical="16dp"
android:layout_marginHorizontal="15dp"
android:text="2024/10/10"
android:textColor="@color/color_666666"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/view_bg" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="15dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/ll_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="12dp"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_icon"
android:layout_width="40dp"
android:layout_height="40dp"
android:src="@mipmap/ic_launcher"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_video"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/img_play_file_small"
app:layout_constraintTop_toTopOf="@id/iv_icon"
app:layout_constraintBottom_toBottomOf="@id/iv_icon"
app:layout_constraintStart_toStartOf="@id/iv_icon"
app:layout_constraintEnd_toEndOf="@id/iv_icon" />
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginHorizontal="8dp"
android:orientation="vertical"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/iv_icon"
app:layout_constraintEnd_toStartOf="@id/iv_select">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:text="@string/app_name"
android:textColor="@color/color_181b1f"
android:textSize="16sp" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_length"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:text="127.6MB"
android:textColor="@color/color_aeb4bd"
android:textSize="12sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_select"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/icon_all_photo_off"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<View
android:id="@+id/view_line"
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:layout_marginTop="12dp"
android:background="@color/color_ebebeb"
app:layout_constraintTop_toBottomOf="@id/ll_content" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="15dp">
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/ll_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="12dp"
android:gravity="center"
android:orientation="horizontal"
app:layout_constraintTop_toTopOf="parent">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ellipsize="end"
android:maxLines="1"
android:text="@string/app_name"
android:textColor="@color/color_666666"
android:textSize="14sp" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_select"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/icon_all_photo_off"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.appcompat.widget.LinearLayoutCompat>
<View
android:id="@+id/view_line"
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:layout_marginTop="12dp"
android:background="@color/color_ebebeb"
app:layout_constraintTop_toBottomOf="@id/ll_content" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_occupies"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="7dp"
android:text="@string/occupies"
android:textColor="@color/color_9b9595"
android:textSize="14sp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="7dp"
android:text="0B"
android:textColor="@color/color_9b9595"
android:textSize="14sp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toEndOf="@id/tv_occupies" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_large"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/tv_occupies">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_first_photo"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_marginTop="4dp"
android:layout_marginStart="15dp"
android:src="@color/black"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_select"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginEnd="8dp"
android:src="@mipmap/ic_check_n_photo"
app:layout_constraintTop_toTopOf="@id/iv_first_photo"
app:layout_constraintEnd_toEndOf="@id/iv_first_photo" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_large_photo"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:layout_marginEnd="15dp"
android:scrollbars="none"
android:nestedScrollingEnabled="false"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/iv_first_photo" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_photo"
android:layout_width="match_parent"
android:layout_height="0dp"
android:paddingHorizontal="15dp"
android:paddingBottom="10dp"
android:scrollbars="none"
android:nestedScrollingEnabled="false"
app:layout_constraintTop_toBottomOf="@id/cl_large" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_photo"
android:layout_width="80dp"
android:layout_height="73dp"
android:layout_marginTop="4dp"
android:src="@color/color_9b9595"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_select"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginEnd="8dp"
android:src="@mipmap/ic_check_n_photo"
app:layout_constraintTop_toTopOf="@id/iv_photo"
app:layout_constraintEnd_toEndOf="@id/iv_photo" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_image"
android:layout_width="84dp"
android:layout_height="84dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_video"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/icon_play_whatsapp"
app:layout_constraintTop_toTopOf="@id/iv_image"
app:layout_constraintBottom_toBottomOf="@id/iv_image"
app:layout_constraintStart_toStartOf="@id/iv_image"
app:layout_constraintEnd_toEndOf="@id/iv_image" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_shadow"
android:layout_width="0dp"
android:layout_height="0dp"
android:src="@drawable/shadow_bg"
app:layout_constraintTop_toTopOf="@id/iv_image"
app:layout_constraintBottom_toBottomOf="@id/iv_image"
app:layout_constraintStart_toStartOf="@id/iv_image"
app:layout_constraintEnd_toEndOf="@id/iv_image" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="+2"
android:textColor="@color/white"
android:textSize="24sp"
android:textStyle="bold"
app:layout_constraintTop_toTopOf="@id/iv_image"
app:layout_constraintBottom_toBottomOf="@id/iv_image"
app:layout_constraintStart_toStartOf="@id/iv_image"
app:layout_constraintEnd_toEndOf="@id/iv_image" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.gms.ads.nativead.NativeAdView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/ad_native_background">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/ad_small_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginStart="6dp"
android:src="@mipmap/icon_ad_pop"
android:tint="@color/colorPrimary"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<com.google.android.gms.ads.nativead.MediaView
android:id="@+id/ad_media"
android:layout_width="0dp"
android:layout_height="130dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="42dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/ad_small_icon" />
<ImageView
android:id="@+id/ad_icon"
android:layout_width="33dp"
android:layout_height="33dp"
android:layout_marginStart="14dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/ad_call_to_action"
app:layout_constraintBottom_toBottomOf="@id/ad_call_to_action" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/ad_headline"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:ellipsize="end"
android:maxLines="2"
android:text="@string/app_name"
android:textColor="@color/black"
android:textSize="16sp"
app:layout_constraintTop_toTopOf="@id/ad_call_to_action"
app:layout_constraintBottom_toBottomOf="@id/ad_call_to_action"
app:layout_constraintStart_toEndOf="@id/ad_icon"
app:layout_constraintEnd_toStartOf="@id/ad_call_to_action" />
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/ad_call_to_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:layout_marginEnd="6dp"
android:paddingStart="20dp"
android:paddingEnd="20dp"
android:text="@string/open"
android:textColor="@color/white"
android:textSize="15sp"
android:textStyle="bold"
android:background="@drawable/gradient_26"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/ad_headline"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/ad_media" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.gms.ads.nativead.NativeAdView>
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.gms.ads.nativead.NativeAdView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp"
android:background="@drawable/ad_native_background">
<com.google.android.gms.ads.nativead.MediaView
android:id="@+id/ad_media"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginEnd="8dp"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintTop_toTopOf="@id/ll_content"
app:layout_constraintBottom_toBottomOf="@id/ll_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/ll_content" />
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/ll_content"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginEnd="4dp"
android:orientation="vertical"
app:layout_constraintHorizontal_weight="1.3"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/ad_media">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/ad_headline"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:ellipsize="end"
android:maxLines="1"
android:text="@string/app_name"
android:textColor="@color/color_181b1f"
android:textSize="12sp" />
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:orientation="horizontal">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/ad_small_icon"
android:layout_width="wrap_content"
android:tint="@color/colorPrimary"
android:layout_height="wrap_content"
android:src="@mipmap/icon_ad_pop"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/ad_body"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="10dp"
android:text="@string/storage_permission_content"
android:ellipsize="end"
android:maxLines="2"
android:textColor="@color/color_666666"
android:textSize="10sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:orientation="horizontal">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/ad_icon"
android:layout_width="33dp"
android:layout_height="33dp" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/ad_call_to_action"
android:layout_width="wrap_content"
android:layout_height="38dp"
android:background="@drawable/gradient_26"
android:text="@string/open"
android:textAllCaps="false"
android:textColor="@color/white"
android:textSize="14sp"
android:textStyle="bold" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.gms.ads.nativead.NativeAdView>
......@@ -8,4 +8,45 @@
<color name="color_ffa127">#FFA127</color>
<color name="color_f92b39">#F92B39</color>
<color name="colo_00b8de">#00B8DE</color>
<color name="color_f7fafa">#F7FAFA</color>
<color name="color_8eb0ff">#8EB0FF</color>
<color name="color_6473f8">#6473F8</color>
<color name="color_2b91f1">#2B91F1</color>
<color name="color_fd891e">#FD891E</color>
<color name="color_ff6400">#FF6400</color>
<color name="color_ff8200">#FF8200</color>
<color name="color_ffe14a">#FFE14A</color>
<color name="color_ffcd58">#FFCD58</color>
<color name="color_ff881d">#FF881D</color>
<color name="color_181b1f">#181B1F</color>
<color name="color_ffb462">#FFB462</color>
<color name="color_ffc889">#FFC889</color>
<color name="color_aeb4bd">#AEB4BD</color>
<color name="color_666666">#666666</color>
<color name="color_ebebeb">#EBEBEB</color>
<color name="color_66000000">#66000000</color>
<color name="color_ff6651">#FF6651</color>
<color name="color_cccccc">#CCCCCC</color>
<color name="color_d9d9d9">#D9D9D9</color>
<color name="color_27d07e">#27D07E</color>
<color name="color_f0f0f0">#F0F0F0</color>
<color name="color_ffae00">#FFAE00</color>
<color name="color_fff5c3">#FFF5C3</color>
<color name="color_ffb764">#FFB764</color>
<color name="color_ffae52">#FFAE52</color>
<color name="color_4f4f4f">#4F4F4F</color>
<color name="color_ffe8ce">#FFE8CE</color>
<color name="color_f8f8fb">#F8F8FB</color>
<color name="color_9b9595">#9B9595</color>
<color name="color_ff9a0c">#FF9A0C</color>
<color name="color_ffc067">#FFC067</color>
<color name="color_fedbbb">#FEDBBB</color>
<color name="color_98a1af">#98A1AF</color>
<color name="color_f9f9fc">#F9F9FC</color>
<color name="color_b5e0ffc">#B5E0FF</color>
<color name="color_e6e6e6">#E6E6E6</color>
<color name="color_f8fbff">#F8FBFF</color>
<color name="color_ffcda0">#FFCDA0</color>
<color name="color_999999">#999999</color>
<color name="color_e3e6eb">#E3E6EB</color>
</resources>
\ No newline at end of file
<resources xmlns:tools="http://schemas.android.com/tools">
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
<string name="app_name" tools:ignore="MissingTranslation">PDF Reader &amp; Scanner</string>
<string name="facebook_app_id" tools:ignore="MissingTranslation">939938294571154</string>
......@@ -127,4 +127,242 @@
<string name="scan">Scan</string>
<string name="app_process">App Process</string>
<string name="create">Create</string>
<string name="history">History</string>
<string name="settings">Settings</string>
<string name="wifi">Wifi</string>
<string name="text">Text</string>
<string name="email">Email</string>
<string name="event">Event</string>
<string name="contact">Contact</string>
<string name="website">Website</string>
<string name="location">Location</string>
<string name="telephone">Telephone</string>
<string name="message">Message</string>
<string name="ssid_wifi">SSID Wifi</string>
<string name="enter_your_ssid_wifi">Enter your ssid wifi</string>
<string name="enter_your_password_wifi">Enter your password wifi</string>
<string name="hidden">Hidden</string>
<string name="select_security_type">Select security type</string>
<string name="select_wifi">Select Wifi</string>
<string name="wpa_wpa2">WPA/WPA2</string>
<string name="wep">WEP</string>
<string name="open">Open</string>
<string name="password">Password</string>
<string name="search_on_the_web">search on the web</string>
<string name="export_to_pdf">Export to PDF</string>
<string name="download">Download</string>
<string name="copy">Copy</string>
<string name="filename">FileName</string>
<string name="content">Content</string>
<string name="enter_your_text_here">Enter your text here</string>
<string name="input_type">Input type</string>
<string name="qr_code">QR Code</string>
<string name="to">To</string>
<string name="enter_address_email">Enter address email</string>
<string name="subject">Subject</string>
<string name="enter_your_message_here">Enter your message here…</string>
<string name="sort">Sort</string>
<string name="export">Export</string>
<string name="remove">Remove</string>
<string name="delete_qrcode">Delete QRCode</string>
<string name="do_you_want_delete_item">Do you want delete item?</string>
<string name="loading">Loading</string>
<string name="product">Product</string>
<string name="daily_new_product_report">Daily new product report</string>
<string name="information_product_notification">Information product notification</string>
<string name="other">Other</string>
<string name="change_language">Change language</string>
<string name="rate_this_app">Rate this app</string>
<string name="send_feedback">Send Feedback</string>
<string name="manage_subscriptions">Manage Subscriptions</string>
<string name="share_app">Share app</string>
<string name="check_app_update">Check app update</string>
<string name="version">"Version "</string>
<string name="no_qrcode">NO QRCode</string>
<string name="choose_language">Choose language</string>
<string name="web_address">Web address</string>
<string name="turn_on_notification">Turn on notification</string>
<string name="turn_on">Turn on</string>
<string name="do_you_want_to_leave_app">Do you want to leave app?</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="search_for_products">Search for products</string>
<string name="search_for_product_information">Search for product information</string>
<string name="new_product">New feature! Search for information about the product.</string>
<string name="what_products">What products are you\nlooking for today?</string>
<string name="find_now">Find Now</string>
<string name="create_now">Create Now</string>
<string name="enjoy_qrcode">Enjoy QRcode?</string>
<string name="your_opinion_matters_to_us">Your opinion matters to us</string>
<string name="rate_now">Rate now</string>
<string name="event_name">Event name</string>
<string name="enter_your_event_location">Enter your event location</string>
<string name="enter_your_event_name">Enter event name</string>
<string name="description">Description</string>
<string name="let_people_know_more_about_the_event">Let people know more about the event</string>
<string name="begin_time">Begin Time</string>
<string name="end_time">End Time</string>
<string name="datetime">DateTime</string>
<string name="phone">Phone</string>
<string name="enter_phone_number">Enter phone number</string>
<string name="select_in_contacts">Select in contacts</string>
<string name="first_fragment_label">First Fragment</string>
<string name="second_fragment_label">Second Fragment</string>
<string name="phone_number">Phone number</string>
<string name="link_website">Link Website</string>
<string name="name">Name</string>
<string name="enter_full_name">Enter full name</string>
<string name="address">Address</string>
<string name="enter_address">Enter address</string>
<string name="enter_telephone_number">Enter telephone number</string>
<string name="enter_email">Enter email</string>
<string name="quickly_scan_products">Quickly scan products</string>
<string name="create_share_qr_code">Create &amp; Share QR Code</string>
<string name="scan_barcode_qr_code">Scan Barcode &amp; QR Code</string>
<string name="guide_1">Scan barcodes and QR codes into images for storage, support sharing</string>
<string name="guide_2">Scan products to obtain prices and other information</string>
<string name="guide_3">Edit the various information you want to share into QR codes</string>
<string name="continue_">Continue</string>
<string name="complete">Complete</string>
<string name="files_manager">Files Manager</string>
<string name="junk_scan">Junk Scan</string>
<string name="battery_info">Battery Info</string>
<string name="whatsapp_clean">WhatsApp Clean</string>
<string name="screenshot_clean">Screenshot Clean</string>
<string name="app_manager">App Manager</string>
<string name="large_file_clean">Large File Clean</string>
<string name="image_compressor">Image Compression</string>
<string name="storage_used">Storage Used</string>
<string name="memory_used">Memory Used</string>
<string name="systematic">Systematic</string>
<string name="read_terms_and_conditions">Read terms and conditions</string>
<string name="rate_us">Rate us</string>
<string name="rate_our_app">Rate our app</string>
<string name="share_app_with_friends">Share app with friends</string>
<string name="found">Found</string>
<string name="normal">Normal</string>
<string name="finish">Finish</string>
<string name="storage_permission_title">Need to obtain storage permissions</string>
<string name="storage_permission_content">To ensure proper functionality,please allow Fast Phone Cleaner to access all files on your device.</string>
<string name="notification_title">Turn on notification</string>
<string name="notification_content">Never miss important phone cleaning notification reminders</string>
<string name="open_settings">Open Settings</string>
<string name="score_title">Thank you for using Fast Phone Cleaner!</string>
<string name="score_content">Five medal express great satisfaction</string>
<string name="sure">Sure</string>
<string name="please_wait_a_moment">Please wait a moment</string>
<string name="logout_content">Are you sure you want to quit without trying to clean up the garbage again?</string>
<string name="already_occupied">Already Occupied</string>
<string name="running_program">Running Program</string>
<string name="skip">Skip</string>
<string name="cleanable">Cleanable</string>
<string name="video_messages">Video Messages</string>
<string name="image_messages">Image Messages</string>
<string name="audio_messages">Audio Messages</string>
<string name="no_video_message_found">No video message found.</string>
<string name="no_image_message_found">No image message found.</string>
<string name="no_audio_message_found">No audio message found.</string>
<string name="found_voice_message">Found 3 audio message(s),unable to listen once cleaned.</string>
<string name="select_all">Select all</string>
<string name="selected">Selected</string>
<string name="delete_title">Sure to delete?</string>
<string name="delete_content">Selected files cannot be recoverd after deleting, continue anyway?</string>
<string name="low">Low</string>
<string name="low_lower">low</string>
<string name="exit_clean_junk">Exit Junk Scan</string>
<string name="exit_clean_junk_content">Exit Junk Scan? Uncleared junk files might be taking up space.</string>
<string name="exit_app_process">Exit App Process</string>
<string name="exit_app_manager_content">Exit App manager? Unused applications may occupy phone memory.</string>
<string name="exit_whatsapp_clean">Exit WhatsApp Clean</string>
<string name="exit_whatsapp_clean_content">Exit WhatsApp Clean? Possible WhatsApp junk files may be using space.</string>
<string name="exit_app_process_content1">Exit App Process?</string>
<string name="exit_app_process_content2">background processes are still running.</string>
<string name="exit_screenshot_cleaner">Exit Screenshot Clean</string>
<string name="exit_screenshot_cleaner_content">Exit Screenshot Clean? Unremoved screenshots may be taking up space.</string>
<string name="exit_similar_photos">Exit Similar Photos</string>
<string name="exit_similar_photos_content">Exit Similar Photos? Unremoved similar photos might be occupying space.</string>
<string name="notification_clean_junk">Clean out junk fles to free up space on your phone!</string>
<string name="notification_whatsapp_clean">Free up space by cleaning up WhatsApp junk files!</string>
<string name="notification_screenshot_clean">Clear screenshot clutter to free up space!</string>
<string name="notification_installed">Installed successfully \nClean up files from your device!</string>
<string name="notification_uninstalled">Uninstalled successfully \nClean up files from your device!</string>
<string name="notification_not_clean">Not cleaned in</string>
<string name="notification_not_clean_days">day(s)</string>
<string name="result_clean_junk">Clean up unnecessary junk files!</string>
<string name="result_app_processes">Manage backend processes</string>
<string name="result_screenshot_clean">Check Screenshot Clean to release more space</string>
<string name="result_similar_photos">Clean up similar photos to free up space</string>
<string name="result_app_manager">Clear out apps you no longer need</string>
<string name="result_whatsapp_clean">Free up space by cleaning up WhatsApp junkfiles</string>
<string name="cleaned_up">Cleaned up</string>
<string name="cleaned_up_content">Cleaned up other data to free up more space</string>
<string name="free_up_phone_space">Free Up Phone Space</string>
<string name="apps">apps</string>
<string name="uninstall">Uninstall</string>
<string name="screenshots_totally">Screenshots totally</string>
<string name="clean_tips">Clean Up doesn\'t Delete Your Personal Data</string>
<string name="empty_folder">Empty Folder</string>
<string name="apk_files">Apk Files</string>
<string name="temp_files">Temp Files</string>
<string name="logs_files">Logs Files</string>
<string name="agree">By continuing you are agreeing to the</string>
<string name="go_it">Go it</string>
<string name="other_than">Other than</string>
<string name="all_types">All types</string>
<string name="image">Image</string>
<string name="video">Video</string>
<string name="audio">Audio</string>
<string name="apk">Apk</string>
<string name="other_types">Other types</string>
<string name="mb_10">10 MB</string>
<string name="mb_20">20 MB</string>
<string name="mb_50">50 MB</string>
<string name="mb_100">100 MB</string>
<string name="mb_500">500 MB</string>
<string name="all_time">All time</string>
<string name="week_1">1 week</string>
<string name="month_1">1 month</string>
<string name="month_3">3 month</string>
<string name="month_6">6 month</string>
<string name="year_1">1 year</string>
<string name="please_wait">Please wait…</string>
<string name="best_quality_photo">Best quality photo</string>
<string name="most_space_saved">Most space saved</string>
<string name="confirm_content">The original photos will be replaced by the compressed ones</string>
<string name="process_ad">This process may contain ads</string>
<string name="app">App</string>
<string name="larger_than">Larger than</string>
<string name="junk_files">Junk Files</string>
<string name="hot">Hot</string>
<string name="hot_tools">Hot Tools</string>
<string name="similar_photos">Similar Photos</string>
<string name="release_space">Release Space</string>
<string name="cleaned">Cleaned</string>
<string name="auto_select">Auto select</string>
<string name="occupies">Occupies</string>
<string name="have_been_with_you_for">Have been with you for</string>
<string name="days">days</string>
<string name="day">day</string>
<string name="the_best_we_can_get">The best we can get</string>
<string name="whatsapp">WhatsApp</string>
<string name="view">View</string>
<string name="loading_point">loading…</string>
<string name="files">Files</string>
<string name="clean_junk_pop">Clean out junk files to free up space on your phone!</string>
<string name="app_process_pop">application process management for a better experience.</string>
<string name="whatsapp_pop">Clear whatsapp file to free up space!</string>
<string name="screen_pop">Clear screenshot clutter to free up space!</string>
<string name="similar_pop">Clear similar file to free up space!</string>
<string name="zodiac">Zodiac</string>
<string name="find_your_screenshot_clean_it">Find your screenshot clean it!</string>
<string name="find_your_large_file_to_clean_it">Find your large file to clean it!</string>
</resources>
\ No newline at end of file
......@@ -20,4 +20,9 @@
<item name="android:background">@android:color/transparent</item>
</style>
<style name="CustomDialogStyle" parent="android:Theme.Material.Dialog">
<item name="android:windowBackground">@android:color/transparent</item>
</style>
</resources>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment