Commit 8bbe0494 authored by wanglei's avatar wanglei

初始化

parent 77dc57b6
*.iml
.gradle
/local.properties
/.idea
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties
/build
\ No newline at end of file
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
id("com.google.gms.google-services")
id("com.google.firebase.crashlytics")
}
android {
namespace = "com.base.pdfreaderallpdfreader"
compileSdk = 34
defaultConfig {
applicationId = "com.base.pdfreaderallpdfreader"
minSdk = 24
targetSdk = 34
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
signingConfigs {
create("release") {
//E6:A2:DD:0A:E6:73:22:32:4E:98:08:78:73:29:01:C4:8D:A0:38:DB:D8:B2:DD:B9:AC:55:69:B2:6B:DF:B0:B4
storeFile = file("../smartcl.jks")
storePassword = "123456"
keyAlias = "key0"
keyPassword = "123456"
}
}
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
// 设置是否要自动上传
// firebaseCrashlytics {
// mappingFileUploadEnabled = true
// }
signingConfig = signingConfigs.getByName("release")
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
buildFeatures {
viewBinding = true
buildConfig = true
}
}
gradle.taskGraph.whenReady {
tasks.forEach { task ->
if (task.name.contains("uploadCrashlyticsMappingFile")) {
task.enabled = false
}
}
}
dependencies {
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.appcompat)
implementation(libs.material)
implementation(libs.androidx.activity)
implementation(libs.androidx.constraintlayout)
implementation(libs.androidx.lifecycle.livedata.ktx)
implementation(libs.androidx.lifecycle.viewmodel.ktx)
implementation(libs.androidx.navigation.fragment.ktx)
implementation(libs.androidx.navigation.ui.ktx)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
//第三方UI
implementation("io.github.cymchad:BaseRecyclerViewAdapterHelper4:4.1.4")
implementation("com.github.angcyo.DslTablayout:TabLayout:3.5.5")
implementation("com.github.angcyo.DslTablayout:ViewPager2Delegate:3.5.5")
implementation("com.airbnb.android:lottie:6.4.0")
implementation("com.github.pokercc:ExpandableRecyclerView:0.9.3")
//mlkit
implementation("com.google.android.gms:play-services-mlkit-document-scanner:16.0.0-beta1")
//Pdf库
implementation("com.tom-roush:pdfbox-android:2.0.27.0")
// api(project(":pdflibrary"))
//
//Word库
//PPT库
//Excel库
// api(project(":library"))
//广告
implementation("com.google.android.gms:play-services-ads:23.1.0")
implementation("com.google.ads.mediation:applovin:12.4.3.0")
implementation("com.google.ads.mediation:facebook:6.17.0.0")
implementation("com.google.ads.mediation:mintegral:16.7.21.0")
implementation("com.google.ads.mediation:pangle:5.9.0.4.0")
//ump
implementation("com.google.android.ump:user-messaging-platform:3.0.0")
//firebase
implementation(platform("com.google.firebase:firebase-bom:32.3.1"))
implementation("com.google.firebase:firebase-messaging")
implementation("com.google.firebase:firebase-analytics-ktx")
implementation("com.google.firebase:firebase-crashlytics")
// implementation("com.google.firebase:firebase-database-ktx")
// implementation("com.google.firebase:firebase-config-ktx")
//facebook
implementation("com.facebook.android:facebook-android-sdk:[8,9)")
//网络请求和解析
implementation("com.google.code.gson:gson:2.11.0")
// define a BOM and its version
implementation(platform("com.squareup.okhttp3:okhttp-bom:4.12.0"))
// define any required OkHttp artifacts without version
implementation("com.squareup.okhttp3:okhttp")
implementation("com.squareup.okhttp3:logging-interceptor")
//mintegral
implementation("com.reyun.solar.engine.oversea:solar-engine-core:1.2.8.3")
}
\ No newline at end of file
{
"project_info": {
"project_number": "618927174476",
"project_id": "scream-11bf5",
"storage_bucket": "scream-11bf5.appspot.com"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:618927174476:android:08858366fed11d3b2455e9",
"android_client_info": {
"package_name": "com.base.pdfreaderallpdfreader"
}
},
"oauth_client": [],
"api_key": [
{
"current_key": "AIzaSyDlEmOxb1M343Tv-FixB0ieQ3NQO0I3ibQ"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": []
}
}
}
],
"configuration_version": "1"
}
\ No newline at end of file
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
\ No newline at end of file
package com.base.pdfreaderallpdfreader
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.base.pdfreaderallpdfreader", appContext.packageName)
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<meta-data
android:name="com.google.mlkit.vision.DEPENDENCIES"
android:value="document_ui" />
<application
android:name=".helper.MyApplication"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.PdfReaderAllPdfReader"
tools:targetApi="31">
<activity
android:name=".ui.document.DocumentActivity"
android:exported="false" />
<activity
android:name=".ui.search.SearchActivity"
android:exported="false" />
<activity
android:name=".ui.splash.SplashActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".ui.main.MainActivity"
android:exported="false"
android:theme="@style/Theme.PdfReaderAllPdfReader.NoActionBar" />
<activity
android:name=".ui.language.LanguageActivity"
android:exported="false"
android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-3940256099942544~3347511713" />
</application>
</manifest>
\ No newline at end of file
package com.base.pdfreaderallpdfreader.base
import android.app.Dialog
import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.viewbinding.ViewBinding
import com.base.pdfreaderallpdfreader.bean.ConstObject.appLanguageSp
import com.base.pdfreaderallpdfreader.bean.ConstObject.changeLanguageSp
import com.base.pdfreaderallpdfreader.helper.EventHelper
import com.base.pdfreaderallpdfreader.ui.main.MainActivity
import com.base.pdfreaderallpdfreader.utils.ActivityLauncher
import com.base.pdfreaderallpdfreader.utils.ActivityManagerUtils
import com.base.pdfreaderallpdfreader.utils.LanguageUtils.changeAppLanguage
import com.base.pdfreaderallpdfreader.utils.LogEx
abstract class BaseActivity<T : ViewBinding> : AppCompatActivity() {
private val TAG = "BaseActivity"
protected abstract val binding: T
lateinit var launcher: ActivityLauncher
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
launcher = ActivityLauncher(this)
setContentView(binding.root)
EventHelper.event("page_${javaClass.simpleName}")
initView()
initListener()
}
protected abstract fun initView()
protected open fun initListener() {}
fun finishToMain() {
if (this !is MainActivity && !ActivityManagerUtils.getInstance().isActivityInStack(MainActivity::class.java)) {
startActivity(Intent(this, MainActivity::class.java))
}
finish()
}
var dialog: Dialog? = null
override fun onDestroy() {
super.onDestroy()
ActivityManagerUtils.getInstance().removeActivity(this)
if (dialog != null) {
dialog?.dismiss()
dialog = null
}
}
override fun onResume() {
super.onResume()
}
fun updateAppLanguage(
activityLanguage: String,
activityTag: String? = null,
activityChangeCallback: ((language: String) -> Unit)? = null
): Boolean {
LogEx.logDebug(
TAG,
"activityTag=$activityTag " +
"appLanguageSp=$appLanguageSp " +
"changeLanguageSp=$changeLanguageSp " +
"activityLanguage=$activityLanguage"
)
var isRecreate = false
if (appLanguageSp != changeLanguageSp || activityLanguage != changeLanguageSp) {
changeAppLanguage(this, changeLanguageSp)
// Restart the app
appLanguageSp = changeLanguageSp
activityChangeCallback?.invoke(changeLanguageSp)
LogEx.logDebug(TAG, "activityTag=$activityTag recreate")
isRecreate = true
//https://stackoverflow.com/questions/63209993/getting-lifecycle-exception-while-recreating-the-activity
//MIUI recreate
this@BaseActivity.recreate()
}
return isRecreate
}
fun checkNeedRecreate(activityLanguage: String): Boolean {
return appLanguageSp != changeLanguageSp || activityLanguage != changeLanguageSp
}
}
\ No newline at end of file
package com.base.pdfreaderallpdfreader.bean
import com.base.pdfreaderallpdfreader.utils.AppPreferences
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale
object ConstObject {
const val MIME_TYPE_IMAGE = "image/*"
const val MIME_TYPE_VIDEO = "video/*"
const val MIME_TYPE_AUDIO = "audio/*"
const val MIME_TYPE_PDF = "application/pdf"
const val MIME_TYPE_DOC = "application/msword"
const val MIME_TYPE_DOCX = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
const val MIME_TYPE_XLS = "application/vnd.ms-excel"
const val MIME_TYPE_XLSX = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
const val MIME_TYPE_PPT = "application/vnd.ms-powerpoint"
const val MIME_TYPE_PPTX = "application/vnd.openxmlformats-officedocument.presentationml.presentation"
const val MIME_TYPE_APK = "application/vnd.android.package-archive"
const val MIME_TYPE_ZIP = "application/zip"
const val DO_SPLIT_PDF = "do_split_pdf"
const val DO_SAVE_PDF = "do_save_pdf"
const val DO_MERGE_PDF = "do_merge_pdf"
const val DO_LOCK_PDF = "do_lock_pdf"
const val DO_UNLOCK_PDF = "do_unlock_pdf"
const val DOCUMENT_DATA_TYPE = "document"
const val RECENT_DATA_TYPE = "recent"
const val BOOKMARK_DATA_TYPE = "bookmark"
const val UI_MODE_NORMAL = "ui_mode_normal"
const val UI_MODE_SELECT = "ui_mode_select"
const val UI_MODE_SEARCH = "ui_mode_search"
const val UI_SORT_LAST_MODIFIED = "ui_sort_last_modified"
const val UI_SORT_FINAL_MODIFIED = "ui_sort_final_modified"
const val UI_SORT_NAME_A_Z = "ui_sort_name_a_z"
const val UI_SORT_NAME_Z_A = "ui_sort_name_z_a"
const val NOTIFICATION_ACTION_LOG = "notification_action_log"
const val NOTIFICATION_ACTION_DOCUMENT = "notification_action_document"
const val NOTIFICATION_ACTION_BOOKMARK = "notification_action_bookmark"
const val NOTIFICATION_ACTION_NEW_IMAGE_PDF = "notification_action_new_image_pdf"
const val NOTIFICATION_ACTION_READ_PDF = "notification_action_read_pdf"
const val NOTIFICATION_ACTION_READ_DOCUMENTS = "notification_action_read_documents"
const val NOTIFICATION_ACTION_UN_VIEW_FILES = "notification_action_un_view_files"
const val NOTIFICATION_ACTION_IMPORTANT_DOCUMENT = "notification_action_important_document"
const val NOTIFICATION_ACTION_APP_PROCESS = "notification_action_app_process"
const val NOTIFICATION_ACTION_CLEAN_JUNK = "notification_action_clean_junk"
const val NOTIFICATION_ACTION_WEATHER = "notification_action_weather"
const val SHORTCUT_SCAN_PDF = "shortcut_scan_pdf"
const val SHORTCUT_SPLIT_PDF = "shortcut_split_pdf"
const val SHORTCUT_MERGE_PDF = "shortcut_merge_pdf"
const val FUNCTION_SCAM_JUNK = "function_scam_junk"
const val FUNCTION_APP_PROCESS = "function_app_process"
var ifAgreePrivacy = false
get() {
return AppPreferences.getInstance().getBoolean("ifAgreePrivacy", field)
}
set(value) {
field = value
AppPreferences.getInstance().put("ifAgreePrivacy", value, true)
}
var haveSaveDemo = false
get() {
return AppPreferences.getInstance().getBoolean("haveSaveDemo", field)
}
set(value) {
field = value
AppPreferences.getInstance().put("haveSaveDemo", value, true)
}
var haveGuideGesture = false
get() {
return AppPreferences.getInstance().getBoolean("haveGuideGesture", field)
}
set(value) {
field = value
AppPreferences.getInstance().put("haveGuideGesture", value, true)
}
var appLanguageSp = Locale.ENGLISH.language
get() {
return AppPreferences.getInstance().getString("appLanguageSp", field)
}
set(value) {
field = value
AppPreferences.getInstance().put("appLanguageSp", value, true)
}
var changeLanguageSp = appLanguageSp
get() {
return AppPreferences.getInstance().getString("changeLanguageSp", field)
}
set(value) {
field = value
AppPreferences.getInstance().put("changeLanguageSp", value, true)
}
var haveSelectLanguage = false
get() {
return AppPreferences.getInstance().getBoolean("selectFollowLanguage", field)
}
set(value) {
field = value
AppPreferences.getInstance().put("selectFollowLanguage", value, true)
}
var selectFollowLanguage = false
get() {
return AppPreferences.getInstance().getBoolean("selectFollowLanguage", field)
}
set(value) {
field = value
AppPreferences.getInstance().put("selectFollowLanguage", value, true)
}
//是否第一次启动
var isFirstStart = true
get() {
return AppPreferences.getInstance().getBoolean("isFirstStart", field)
}
set(value) {
field = value
AppPreferences.getInstance().put("isFirstStart", value, true)
}
//主页启动次数
var mainStartTimes = 0
get() {
return AppPreferences.getInstance().getInt("mainStartTimes", field)
}
set(value) {
field = value
AppPreferences.getInstance().put("mainStartTimes", value, true)
}
var todayShowNotificationDialog = false
get() {
return AppPreferences.getInstance().getBoolean("todayShowNotificationDialog_${currentDate()}", field)
}
set(value) {
field = value
AppPreferences.getInstance().put("todayShowNotificationDialog_${currentDate()}", value, true)
}
var setDefault = false
get() {
return AppPreferences.getInstance().getBoolean("setDefault", field)
}
set(value) {
field = value
AppPreferences.getInstance().put("setDefault", value, true)
}
private fun currentDate(): String {
val dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
val currentDate = Calendar.getInstance().time
return dateFormat.format(currentDate)
}
}
\ No newline at end of file
package com.base.pdfreaderallpdfreader.bean
import android.net.Uri
data class DocumentBean(
var path: String = "",
var uri: Uri = Uri.EMPTY,
var type: String = "",
var isBookmarked: Boolean = false,
) {
var uiType: Int = 0//0首页模式 1合并选择模式 2拆分模式 3解锁加锁模式 4搜索模式
var isSelect: Boolean = false
var state: Int = -1//0正常状态 1 锁定
var password: String = ""
var lastViewTime: Long = 0
var isAd: Boolean = false
companion object {
const val TYPE_PDF = "type_pdf"
const val TYPE_WORD = "type_word"
const val TYPE_EXCEL = "type_excel"
const val TYPE_PPT = "type_ppt"
}
}
package com.base.pdfreaderallpdfreader.bean
data class LanguageBean(
val key: String,
val language: String,
val country: String,
) {
var isSelect: Boolean = false
var isFollowSystem: Boolean = false
companion object {
const val English = "English"
const val 简体中文 = "简体中文"
const val português = "português"
const val Español = "Español "
const val Français = "Français"
const val Deutsch = "Deutsch"
const val ไทย = "ไทย"
const val Bahasa_Indonesia = "Bahasa Indonesia"
const val Melayu = "Melayu"
const val Tiếng_Việt = "Tiếng Việt"
const val 日本語 = "日本語"
const val Italiano = "Italiano"
const val 한국인 = "한국인"
const val Nederlands = "Nederlands"
const val 繁體中文 = "繁體中文"
const val Türk = "Türk"
}
}
\ No newline at end of file
package com.base.pdfreaderallpdfreader.bean
import android.net.Uri
data class MediaBean(
val path: String = "",
val uri: Uri = Uri.EMPTY,
val mimeType: String = ""
)
package com.base.pdfreaderallpdfreader.helper
import android.util.Base64
import java.security.SecureRandom
import javax.crypto.Cipher
import javax.crypto.spec.GCMParameterSpec
import javax.crypto.spec.SecretKeySpec
object AESHelper {
private const val aesKey = "7vwdrlk6bp8rihe4"
private val cipher by lazy {
Cipher.getInstance("AES/GCM/NoPadding")
}
fun encrypt(content: String): String {
try {
val iv = ByteArray(12).apply {
SecureRandom().nextBytes(this)
}
val contentBytes = content.toByteArray(Charsets.UTF_8)
val params = GCMParameterSpec(128, iv)
cipher.init(
Cipher.ENCRYPT_MODE,
secretKey, params
)
val encryptData = cipher.doFinal(contentBytes)
if (encryptData.size != contentBytes.size + 16) {
throw IllegalStateException("Encryption failed")
}
val message = ByteArray(12 + contentBytes.size + 16)
System.arraycopy(iv, 0, message, 0, 12)
System.arraycopy(encryptData, 0, message, 12, encryptData.size)
return String(Base64.encode(message, Base64.NO_WRAP), Charsets.UTF_8)
} catch (_: Exception) {
}
return content
}
@Synchronized
fun decrypt(content: String): String {
try {
val con = content.replace(" ".toRegex(), "+")
val contentByte = Base64.decode(con, Base64.NO_WRAP)
require(contentByte.size >= 12 + 16)
val params = GCMParameterSpec(128, contentByte, 0, 12)
cipher.init(
Cipher.DECRYPT_MODE,
secretKey, params
)
val decryptData = cipher.doFinal(contentByte, 12, contentByte.size - 12)
return String(decryptData, Charsets.UTF_8)
} catch (_: Exception) {
}
return content
}
private val secretKey by lazy {
SecretKeySpec(aesKey.toByteArray(), "AES")
}
}
\ No newline at end of file
package com.base.pdfreaderallpdfreader.helper
import com.base.pdfreaderallpdfreader.ui.splash.SplashActivity
object ConfigHelper {
const val privacyPolicy: String = "https://sites.google.com/view/pdf-reader-scan/pdf-reader"
const val termService: String = "https://sites.google.com/view/term-of-service-s/term-of-service"
// 正式包名
const val packageName = "com.lol.pdfscanner.libstdc.chovey"
// 域名
const val eventUrl = "https://rp.gamexzonerk.xyz"
const val apiUrl = "https://api.gamexzonerk.xyz"
//admob test id
const val openAdmobIdTest = "ca-app-pub-3940256099942544/9257395921"
const val bannerAdmobIdTest = "ca-app-pub-3940256099942544/9214589741"
const val interAdmobIdTest = "ca-app-pub-3940256099942544/1033173712"
const val nativeAdmobIdTest = "ca-app-pub-3940256099942544/2247696110"
// admob广告id
const val interAdmobId = "ca-app-pub-3940256099942544/1033173111"
const val nativeAdmobId = "ca-app-pub-3940256099942544/2247696111"
const val openAdmobId = "/6499/example/app-open"
const val bannerAdmobId = "ca-app-pub-3940256099942544/9214581111"
val noLoadingActivities = listOf(
"full", // 过滤全屏广告
"adActivity",
"AdActivity",
"AppLovinFullscreenActivity",
SplashActivity::class.java.simpleName,
"GmsDocumentScanningDelegateActivity",
// 返回前台时不跳转启动页的 activity
)
}
\ No newline at end of file
package com.base.pdfreaderallpdfreader.helper
import android.os.Build
import com.base.pdfreaderallpdfreader.bean.ConstObject.ifAgreePrivacy
import com.base.pdfreaderallpdfreader.helper.ReportUtils.doPost
import com.base.pdfreaderallpdfreader.utils.AppPreferences
import com.base.pdfreaderallpdfreader.utils.LogEx
import org.json.JSONException
import org.json.JSONObject
object EventHelper {
private val TAG = "EventUtils"
fun event(
key: String,
value: String? = null,
ext: JSONObject? = null,
isSingleEvent: Boolean = false
) {
if (!ifAgreePrivacy) {
return
}
if (isSingleEvent) {
val stringSet = AppPreferences.getInstance().getStringSet("singleEvent", setOf())
if (stringSet.contains(key)) {
return
}
}
Thread {
var paramJson: String? = ""
try {
val pkg = ConfigHelper.packageName
val s = JSONObject()
.put("action", key)
.put("value", value)
.put("ext", ext)
val s2 = getBp()
val data = JSONObject()
.put("data", s)
.put("bp", s2)
.toString()
LogEx.logDebug(TAG, "uuid=${AppPreferences.getInstance().getString("uuid", "")}")
LogEx.logDebug(TAG, "gid=${AppPreferences.getInstance().getString("gid", "")}")
paramJson = AESHelper.encrypt(data)
} catch (e: JSONException) {
paramJson = ""
}
LogEx.logDebug(TAG, "url=$url")
doPost(
url,
HashMap(),
paramJson
)
}.start()
}
private val url by lazy {
val pkg = ConfigHelper.packageName
val url = StringBuilder(
"${ConfigHelper.eventUrl}/${
pkg.filter { it.isLowerCase() }.substring(4, 9)
}sp"
)
url.append("?pkg=$pkg")
url.toString()
}
fun getBp(): JSONObject {
val pkg = ConfigHelper.packageName
val s2 = JSONObject()
.put("${pkg}_3", AppPreferences.getInstance().getString("Equipment", ""))
.put("${pkg}_4", AppPreferences.getInstance().getString("Manufacturer", ""))
.put("${pkg}_5", Build.VERSION.SDK_INT)
.put("${pkg}_9", AppPreferences.getInstance().getString("uuid", ""))
.put("${pkg}_10", AppPreferences.getInstance().getString("gid", ""))
.put("${pkg}_13", "android")
.put("${pkg}_15", "google")
// .put("${pkg}_14", BuildConfig.VERSION_CODE)
// .put("${pkg}_8", BuildConfig.VERSION_NAME)
// .put("${pkg}_24", BuildConfig.BUILD_TYPE)
return s2
}
}
\ No newline at end of file
package com.base.pdfreaderallpdfreader.helper
import android.app.Activity
import android.app.Application
import android.content.Intent
import android.os.Bundle
import android.text.TextUtils
import com.base.pdfreaderallpdfreader.ui.splash.SplashActivity
import com.base.pdfreaderallpdfreader.utils.ActivityManagerUtils
import com.base.pdfreaderallpdfreader.utils.AppPreferences
import com.base.pdfreaderallpdfreader.utils.LogEx
import com.facebook.FacebookSdk
import com.tom_roush.pdfbox.android.PDFBoxResourceLoader
import java.util.Locale
import java.util.UUID
class MyApplication : Application() {
private val TAG = "MyApplication"
var uuid = ""
companion object {
lateinit var context: MyApplication
var splashLanguage: String = Locale.getDefault().language
var mainLanguage: String = Locale.getDefault().language
var setLanguage: String = Locale.getDefault().language
var feedbackLanguage: String = Locale.getDefault().language
var pptLanguage: String = Locale.getDefault().language
var pdfLanguage: String = Locale.getDefault().language
var pdfLoadingLanguage: String = Locale.getDefault().language
var pdfMergeLanguage: String = Locale.getDefault().language
var pdfSelectLanguage: String = Locale.getDefault().language
var pdfSplitLanguage: String = Locale.getDefault().language
var wordLanguage: String = Locale.getDefault().language
@JvmField
var PAUSED_VALUE = 0
}
override fun onCreate() {
super.onCreate()
context = this
initUUid()
initApp()
PDFBoxResourceLoader.init(applicationContext)
// initWeather()
}
// private fun initWeather() {
// requestWeatherData()
// }
private fun initUUid() {
uuid = AppPreferences.getInstance().getString("uuid", "")
if (TextUtils.isEmpty(uuid)) {
uuid = UUID.randomUUID().toString() + System.currentTimeMillis()
AppPreferences.getInstance().put("uuid", uuid)
LogEx.logDebug(TAG, "uuid=$uuid")
}
}
fun initApp() {
// SolarEngineManager.getInstance().preInit(context, "81a11caa4076cd7c")
// FacebookSdk.sdkInitialize(applicationContext)
// var topicNumber = System.currentTimeMillis().toFormatMinute()
// LogEx.logDebug(TAG, "topicNumber=$topicNumber")
// if (topic_number.isNotEmpty()) {
// topicNumber = topic_number
// } else {
// topic_number = topicNumber
// }
// val topic = ConfigHelper.packageName + "_push_$topicNumber"
val topic = ConfigHelper.packageName + "_push"
LogEx.logDebug(TAG, "topic=${topic}")
// FCMManager.initFirebase(this)
// FCMManager.subscribeToTopic(topic)
// InstallHelps.init()
initLifeListener()
// ScreenStatusReceiver.setupScreenStatusListener(this)
}
// fun initSolarEngine(gdprDeny: Boolean = false) {
//
// val configBuilder = SolarEngineConfig.Builder()
//
// if (BuildConfig.DEBUG) {
// configBuilder.logEnabled() //开启本地调试日志
// }
// if (gdprDeny) {
// configBuilder.isGDPRArea = true
// configBuilder.adPersonalizationEnabled = true
// configBuilder.adUserDataEnabled = true
// }
// configBuilder.isCoppaEnabled = true
// configBuilder.setKidsAppEnabled(true)
// configBuilder.fbAppID = ""
//
// val config = configBuilder.build()
//
// SolarEngineManager.getInstance().initialize(context, "81a11caa4076cd7c", config,
// OnInitializationCallback { code ->
// if (code == 0) {
// //初始化成功
// config.setOnAttributionListener(object : OnAttributionListener {
// override fun onAttributionSuccess(attribution: JSONObject) {
// //获取归因结果成功时执行的动作
// LogEx.logDebug(TAG, "attribution=$attribution")
// EventHelper.event("install_referrer", attribution.toString())
// }
//
// override fun onAttributionFail(errorCode: Int) {
// //获取归因结果失败时执行的动作
// EventHelper.event("SolarEngineManager onAttributionFail errorCode=$errorCode")
// }
// })
// } else {
// //初始化失败,具体失败原因参考下方code码释义
// EventHelper.event("SolarEngineManager init error code=$code")
// }
// })
// }
private var lastTimePause = 0L
private var lastTimeResume = 0L
private fun isHotLaunch(): Boolean {
if ((lastTimeResume - lastTimePause) > 5000) {
return true
}
return false
}
private fun initLifeListener() {
registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks {
private var count = 0
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
ActivityManagerUtils.getInstance().addActivity(activity)
}
override fun onActivityStarted(activity: Activity) {
count++
lastTimeResume = System.currentTimeMillis()
if (count == 1 && isHotLaunch()) {
val topActivity: Activity? = ActivityManagerUtils.getInstance().topActivity
val flag = if (topActivity == null) {
true
} else {
ConfigHelper.noLoadingActivities.all { !topActivity.localClassName.contains(it, true) }
}
LogEx.logDebug(TAG, "flag=$flag" + " activity:" + activity.localClassName)
if (flag) {
topActivity?.startActivity(
Intent(
topActivity, SplashActivity::class.java
).apply {
putExtra("isHotLaunch", true)
putExtra("type", -1)
})
}
}
lastTimeResume = 0
}
override fun onActivityResumed(activity: Activity) {
// LogEx.logDebug(TAG, "onActivityResumed")
PAUSED_VALUE = 1
}
override fun onActivityPaused(activity: Activity) {
// LogEx.logDebug(TAG, "onActivityPaused")
PAUSED_VALUE = 2
lastTimePause = System.currentTimeMillis()
}
override fun onActivityStopped(activity: Activity) {
count--
}
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
override fun onActivityDestroyed(activity: Activity) {
ActivityManagerUtils.getInstance().removeActivity(activity)
}
})
}
}
\ No newline at end of file
package com.base.pdfreaderallpdfreader.helper;
import android.text.TextUtils;
import com.base.pdfreaderallpdfreader.utils.LogEx;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;
public class ReportUtils {
private static String TAG = "ReportUtils";
public static String doPost(String urlPath, Map<String, String> paramsMap, String json) {
try {
HttpURLConnection conn = (HttpURLConnection) new URL(urlPath).openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.setConnectTimeout(600000);
if (!TextUtils.isEmpty(json)) {
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestProperty("Content-Length", Integer.toString(json.getBytes().length));
conn.getOutputStream().write(json.getBytes());
}
StringBuilder result = new StringBuilder();
for (Map.Entry<String, String> entry : paramsMap.entrySet()) {
result.append("&").append(entry.getKey()).append("=").append(entry.getValue());
}
if (result.length() > 0) {
conn.getOutputStream().write(result.substring(1).getBytes());
} else {
// conn.getOutputStream().write(result.substring(0).getBytes());
}
if (conn.getResponseCode() == 200) {
String s = new BufferedReader(new InputStreamReader(conn.getInputStream())).readLine();
if (!TextUtils.isEmpty(s)) {
} else {
s = "";
}
LogEx.INSTANCE.logDebug(TAG, "code=200", false);
return s;
} else {
LogEx.INSTANCE.logDebug(TAG, "code!=200", false);
}
} catch (Exception e) {
e.printStackTrace();
}
return "{ \"success\": false,\n \"errorMsg\": \"后台服务器开小差了!\",\n \"result\":{}}";
}
}
package com.base.pdfreaderallpdfreader.ui.document
import android.graphics.Color
import android.text.Spannable
import android.text.SpannableString
import android.text.style.ForegroundColorSpan
import androidx.activity.addCallback
import androidx.core.view.updatePadding
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.viewpager2.adapter.FragmentStateAdapter
import androidx.viewpager2.widget.ViewPager2
import com.angcyo.tablayout.delegate2.ViewPager2Delegate
import com.base.pdfreaderallpdfreader.R
import com.base.pdfreaderallpdfreader.base.BaseActivity
import com.base.pdfreaderallpdfreader.bean.DocumentBean
import com.base.pdfreaderallpdfreader.databinding.ActivityDocumentBinding
import com.base.pdfreaderallpdfreader.utils.BarUtils
class DocumentActivity : BaseActivity<ActivityDocumentBinding>() {
private lateinit var documentViewModel: DocumentViewModel
override val binding: ActivityDocumentBinding by lazy {
ActivityDocumentBinding.inflate(layoutInflater)
}
private val allPage: DocumentFragment by lazy {
DocumentFragment("All")
}
private val pdfPage: DocumentFragment by lazy {
DocumentFragment(DocumentBean.TYPE_PDF)
}
private val wordPage: DocumentFragment by lazy {
DocumentFragment(DocumentBean.TYPE_WORD)
}
private val excelPage: DocumentFragment by lazy {
DocumentFragment(DocumentBean.TYPE_EXCEL)
}
private val pptPage: DocumentFragment by lazy {
DocumentFragment(DocumentBean.TYPE_PPT)
}
private val fragments by lazy {
mutableListOf(allPage, pdfPage, wordPage, excelPage, pptPage)
}
override fun initView() {
BarUtils.setStatusBarLightMode(this, true)
BarUtils.setStatusBarColor(this, Color.WHITE)
binding.root.updatePadding(top = BarUtils.getStatusBarHeight())
documentViewModel = ViewModelProvider(this)[DocumentViewModel::class.java]
val spannableString = SpannableString(this.getString(R.string.pdf_reader))
spannableString.setSpan(ForegroundColorSpan(Color.parseColor("#E20001")), 0, 3, Spannable.SPAN_INCLUSIVE_INCLUSIVE)
binding.tvTittle.text = spannableString
initViewPager2()
initTabLayout()
}
private var pageAdapter: FragmentStateAdapter? = null
private fun initViewPager2() {
pageAdapter = object : FragmentStateAdapter(this) {
override fun getItemCount(): Int {
return fragments.size
}
override fun createFragment(position: Int): Fragment {
return fragments[position]
}
}
binding.viewPager2.run {
isUserInputEnabled = true
//https://www.jianshu.com/p/f69bd30cf5b0
//FragmentStateAdapter 这里必须传人fragment
adapter = pageAdapter
}
binding.viewPager2.registerOnPageChangeCallback(object :
ViewPager2.OnPageChangeCallback() {
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
super.onPageScrolled(position, positionOffset, positionOffsetPixels)
}
override fun onPageSelected(position: Int) {
}
})
}
private fun initTabLayout() {
val allColor = Color.parseColor("#2287FE")
val pdfColor = Color.parseColor("#F40000")
val wordColor = Color.parseColor("#2287FE")
val excelColor = Color.parseColor("#1ABE5D")
val pptColor = Color.parseColor("#FF9E0E")
val deselectColor = Color.parseColor("#8F8F8F")
binding.tabLayoutDocument.apply {
configTabLayoutConfig {
tabDeselectColor = deselectColor
onSelectIndexChange = { fromIndex, selectIndexList, reselect, fromUser ->
val toIndex = selectIndexList.first()
binding.viewPager2.currentItem = toIndex
when (toIndex) {
0 -> {
tabSelectColor = allColor
tabIndicator.indicatorColor = allColor
}
1 -> {
tabSelectColor = pdfColor
tabIndicator.indicatorColor = pdfColor
}
2 -> {
tabSelectColor = wordColor
tabIndicator.indicatorColor = wordColor
}
3 -> {
tabSelectColor = excelColor
tabIndicator.indicatorColor = excelColor
}
4 -> {
tabSelectColor = pptColor
tabIndicator.indicatorColor = pptColor
}
}
dslSelector.updateStyle()
}
}
}
ViewPager2Delegate.install(binding.viewPager2, binding.tabLayoutDocument)
}
override fun initListener() {
super.initListener()
onBackPressedDispatcher.addCallback {
finishToMain()
}
binding.flFanhui.setOnClickListener {
onBackPressedDispatcher.onBackPressed()
}
}
}
\ No newline at end of file
package com.base.pdfreaderallpdfreader.ui.document
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.lifecycleScope
import com.base.pdfreaderallpdfreader.bean.DocumentBean
import com.base.pdfreaderallpdfreader.bean.DocumentBean.Companion.TYPE_EXCEL
import com.base.pdfreaderallpdfreader.bean.DocumentBean.Companion.TYPE_PDF
import com.base.pdfreaderallpdfreader.bean.DocumentBean.Companion.TYPE_PPT
import com.base.pdfreaderallpdfreader.bean.DocumentBean.Companion.TYPE_WORD
import com.base.pdfreaderallpdfreader.databinding.FragmentDocumentBinding
import com.base.pdfreaderallpdfreader.ui.main.DocumentAdapter
import com.base.pdfreaderallpdfreader.ui.main.getAllDocument
import com.base.pdfreaderallpdfreader.ui.main.getExcelDocument
import com.base.pdfreaderallpdfreader.ui.main.getPdfDocument
import com.base.pdfreaderallpdfreader.ui.main.getPptDocument
import com.base.pdfreaderallpdfreader.ui.main.getWordDocument
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class DocumentFragment() : Fragment() {
private var type = TYPE_PDF
private lateinit var binding: FragmentDocumentBinding
private var adapter: DocumentAdapter? = null
constructor(type: String) : this() {
this.type = type
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentDocumentBinding.inflate(layoutInflater)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
adapter = DocumentAdapter()
binding.rv.adapter = adapter
}
override fun onResume() {
super.onResume()
if (type == TYPE_PDF) {
if (pdfNeedRefresh) {
pdfNeedRefresh = false
initData()
}
} else {
initData()
}
}
private fun initData() {
binding.swipeRefreshLayout.isRefreshing = true
lifecycleScope.launch(Dispatchers.IO) {
val list: List<DocumentBean>
when (type) {
TYPE_PDF -> {
list = getPdfDocument(requireContext())
}
TYPE_WORD -> {
list = getWordDocument(requireContext())
}
TYPE_EXCEL -> {
list = getExcelDocument(requireContext())
}
TYPE_PPT -> {
list = getPptDocument(requireContext())
}
else -> {
list = getAllDocument(requireContext())
}
}
launch(Dispatchers.Main) {
if (list.isEmpty()) {
binding.llEmpty.visibility = View.VISIBLE
adapter?.submitList(listOf())
} else {
binding.llEmpty.visibility = View.GONE
adapter?.submitList(list)
}
binding.swipeRefreshLayout.isRefreshing = false
}
}
}
companion object {
var pdfNeedRefresh: Boolean = true
}
}
\ No newline at end of file
package com.base.pdfreaderallpdfreader.ui.document
import androidx.lifecycle.ViewModel
class DocumentViewModel : ViewModel() {
}
\ No newline at end of file
package com.base.pdfreaderallpdfreader.ui.language
import android.graphics.Color
import androidx.activity.addCallback
import androidx.core.view.updatePadding
import com.base.pdfreaderallpdfreader.R
import com.base.pdfreaderallpdfreader.base.BaseActivity
import com.base.pdfreaderallpdfreader.bean.ConstObject
import com.base.pdfreaderallpdfreader.bean.ConstObject.appLanguageSp
import com.base.pdfreaderallpdfreader.bean.ConstObject.changeLanguageSp
import com.base.pdfreaderallpdfreader.bean.ConstObject.haveSelectLanguage
import com.base.pdfreaderallpdfreader.bean.LanguageBean
import com.base.pdfreaderallpdfreader.databinding.ActivityLanguageBinding
import com.base.pdfreaderallpdfreader.utils.BarUtils
import java.util.Locale
class LanguageActivity : BaseActivity<ActivityLanguageBinding>() {
override val binding: ActivityLanguageBinding by lazy {
ActivityLanguageBinding.inflate(layoutInflater)
}
private lateinit var adapter: LanguageAdapter
private var from: String = ""
override fun initView() {
BarUtils.setStatusBarLightMode(this, true)
BarUtils.setStatusBarColor(this, Color.WHITE)
binding.root.updatePadding(top = BarUtils.getStatusBarHeight())
from = intent.extras?.getString("from", "") ?: ""
adapter = LanguageAdapter()
binding.rv.adapter = adapter
// AdmobNativeUtils.showNativeAd(this, binding.flAd)
initData()
}
override fun initListener() {
super.initListener()
onBackPressedDispatcher.addCallback {
if (from == "Set") {
finish()
} else {
// startActivity(Intent(this@LanguageActivity, PermissionActivity::class.java))
finish()
}
}
binding.flFanhui.setOnClickListener {
onBackPressedDispatcher.onBackPressed()
}
binding.ivRight.setOnClickListener {
val item = adapter.items.find { it.isSelect }
val selectLanguage = item?.language ?: Locale.ENGLISH.language
if (changeLanguageSp != selectLanguage) {
changeLanguageSp = selectLanguage
}
ConstObject.selectFollowLanguage = item?.isFollowSystem == true
onBackPressedDispatcher.onBackPressed()
}
}
private fun initData() {
val list = listOf(
LanguageBean(
this.getString(R.string.follow_system),
Locale.getDefault().language,
Locale.getDefault().country
).apply { isFollowSystem = true },
LanguageBean(LanguageBean.English, Locale.ENGLISH.language, Locale.ENGLISH.country),
LanguageBean(LanguageBean.简体中文, Locale.SIMPLIFIED_CHINESE.language, Locale.SIMPLIFIED_CHINESE.country),
LanguageBean(LanguageBean.português, Locale("pt", "BR").language, Locale("pt", "BR").country),
LanguageBean(LanguageBean.Español, Locale("es").language, Locale("es").country),
LanguageBean(LanguageBean.Français, Locale.FRENCH.language, Locale.FRENCH.country),
LanguageBean(LanguageBean.Deutsch, Locale.GERMAN.language, Locale.GERMAN.country),
LanguageBean(LanguageBean.ไทย, Locale("th", "TH").language, Locale("th", "TH").country),
LanguageBean(LanguageBean.Bahasa_Indonesia, Locale("in", "ID").language, Locale("in", "ID").country),
LanguageBean(LanguageBean.Melayu, Locale("ms", "MY").language, Locale("ms", "MY").country),
LanguageBean(LanguageBean.Tiếng_Việt, Locale("vi", "VN").language, Locale("vi", "VN").country),
LanguageBean(LanguageBean.日本語, Locale.JAPAN.language, Locale.JAPAN.country),
LanguageBean(LanguageBean.Italiano, Locale.ITALY.language, Locale.ITALY.country),
LanguageBean(LanguageBean.한국인, Locale.KOREAN.language, Locale.KOREAN.country),
LanguageBean(LanguageBean.Nederlands, Locale("nl", "NL").language, Locale("nl", "NL").country),
LanguageBean(LanguageBean.繁體中文, Locale.TRADITIONAL_CHINESE.language, Locale.TRADITIONAL_CHINESE.country),
LanguageBean(LanguageBean.Türk, Locale("tr", "TR").language, Locale("tr", "TR").country),
)
if (ConstObject.selectFollowLanguage || !ConstObject.haveSelectLanguage) {
list.first().isSelect = true
} else {
list.findLast { it.language == appLanguageSp }?.isSelect = true
}
adapter.submitList(list)
haveSelectLanguage = true
}
}
\ No newline at end of file
package com.base.pdfreaderallpdfreader.ui.language
import android.annotation.SuppressLint
import android.content.Context
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.base.pdfreaderallpdfreader.R
import com.base.pdfreaderallpdfreader.bean.LanguageBean
import com.base.pdfreaderallpdfreader.databinding.ItemLanguageSetBinding
import com.base.pdfreaderallpdfreader.utils.XmlEx.inflate
import com.chad.library.adapter4.BaseQuickAdapter
class LanguageAdapter : BaseQuickAdapter<LanguageBean, LanguageAdapter.LanguageViewHolder>() {
inner class LanguageViewHolder(view: View) : ViewHolder(view)
@SuppressLint("NotifyDataSetChanged")
override fun onBindViewHolder(holder: LanguageViewHolder, position: Int, item: LanguageBean?) {
item ?: return
val binding = ItemLanguageSetBinding.bind(holder.itemView)
binding.ivSelector.isSelected = item.isSelect
binding.tvLanguage.text = item.key
binding.root.setOnClickListener {
items.find { it.isSelect }?.isSelect = false
item.isSelect = true
notifyDataSetChanged()
}
}
override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): LanguageViewHolder {
return LanguageViewHolder(R.layout.item_language_set.inflate(parent))
}
}
\ No newline at end of file
package com.base.pdfreaderallpdfreader.ui.main
import android.annotation.SuppressLint
import android.content.Context
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.base.pdfreaderallpdfreader.R
import com.base.pdfreaderallpdfreader.bean.DocumentBean
import com.base.pdfreaderallpdfreader.bean.DocumentBean.Companion.TYPE_EXCEL
import com.base.pdfreaderallpdfreader.bean.DocumentBean.Companion.TYPE_PDF
import com.base.pdfreaderallpdfreader.bean.DocumentBean.Companion.TYPE_PPT
import com.base.pdfreaderallpdfreader.bean.DocumentBean.Companion.TYPE_WORD
import com.base.pdfreaderallpdfreader.databinding.ItemDocumentBinding
import com.base.pdfreaderallpdfreader.utils.KotlinExt.toFormatSize
import com.base.pdfreaderallpdfreader.utils.KotlinExt.toFormatTime5
import com.base.pdfreaderallpdfreader.utils.LogEx
import com.base.pdfreaderallpdfreader.utils.XmlEx.inflate
import com.chad.library.adapter4.BaseQuickAdapter
import java.io.File
class DocumentAdapter : BaseQuickAdapter<DocumentBean, DocumentAdapter.DocumentViewHolder>() {
private val TAG = "DocumentAdapter"
inner class DocumentViewHolder(view: View) : ViewHolder(view)
var moreAction: ((item: DocumentBean) -> Unit)? = null
@SuppressLint("SetTextI18n")
override fun onBindViewHolder(holder: DocumentViewHolder, position: Int, item: DocumentBean?) {
item ?: return
val binding = ItemDocumentBinding.bind(holder.itemView)
when (item.type) {
TYPE_PDF -> {
LogEx.logDebug(TAG, "pdf state = ${item.state}")
if (item.state == 0) {
binding.ivIcon.setImageResource(R.mipmap.r_pdf)
} else {
binding.ivIcon.setImageResource(R.mipmap.rv_pdf_lock)
}
}
TYPE_WORD -> {
binding.ivIcon.setImageResource(R.mipmap.rv_word)
}
TYPE_EXCEL -> {
binding.ivIcon.setImageResource(R.mipmap.rv_excel)
}
TYPE_PPT -> {
binding.ivIcon.setImageResource(R.mipmap.r_ppt)
}
}
val file = File(item.path)
binding.tvName.text = file.name
binding.tvInfo.text = file.lastModified().toFormatTime5() + " " + file.length().toFormatSize()
binding.flMore.setOnClickListener {
moreAction?.invoke(item)
}
}
override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): DocumentViewHolder {
return DocumentViewHolder(R.layout.item_document.inflate(parent))
}
}
\ No newline at end of file
package com.base.pdfreaderallpdfreader.ui.main
import android.content.Context
import android.media.MediaScannerConnection
import android.net.Uri
import com.base.pdfreaderallpdfreader.bean.ConstObject
import com.base.pdfreaderallpdfreader.bean.ConstObject.MIME_TYPE_DOC
import com.base.pdfreaderallpdfreader.bean.ConstObject.MIME_TYPE_DOCX
import com.base.pdfreaderallpdfreader.bean.ConstObject.MIME_TYPE_PDF
import com.base.pdfreaderallpdfreader.bean.ConstObject.MIME_TYPE_PPT
import com.base.pdfreaderallpdfreader.bean.ConstObject.MIME_TYPE_PPTX
import com.base.pdfreaderallpdfreader.bean.ConstObject.MIME_TYPE_XLS
import com.base.pdfreaderallpdfreader.bean.ConstObject.MIME_TYPE_XLSX
import com.base.pdfreaderallpdfreader.bean.DocumentBean
import com.base.pdfreaderallpdfreader.bean.DocumentBean.Companion.TYPE_EXCEL
import com.base.pdfreaderallpdfreader.bean.DocumentBean.Companion.TYPE_PDF
import com.base.pdfreaderallpdfreader.bean.DocumentBean.Companion.TYPE_PPT
import com.base.pdfreaderallpdfreader.bean.DocumentBean.Companion.TYPE_WORD
import com.base.pdfreaderallpdfreader.bean.MediaBean
import com.base.pdfreaderallpdfreader.utils.AssetUtils.readByteArrayFromAsset
import com.base.pdfreaderallpdfreader.utils.PdfBoxUtils.checkPdfEncryption
import com.base.pdfreaderallpdfreader.utils.getMediaFile
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
fun Context.upDateDemoStore() {
val demoFile = File(filesDir, "demo")
MediaScannerConnection.scanFile(
this, arrayOf(demoFile.absolutePath), null
) { path: String?, uri: Uri? -> }
}
fun Context.saveAssetsFile() {
val demoFile = File(filesDir, "demo")
demoFile.mkdirs()
arrayOf(
"DEMO.pdf",
"DEMO.docx",
"DEMO.xlsx",
"DEMO.pptx"
).forEach {
val file = File(demoFile, it)
if (file.exists() && file.length() != 0L) {
return
}
file.createNewFile()
try {
FileOutputStream(file).use { fos -> fos.write(readByteArrayFromAsset(it)) }
} catch (e: IOException) {
e.printStackTrace()
}
}
}
fun getPdfDemo(context: Context): DocumentBean {
val demoDocumentBean = DocumentBean()
demoDocumentBean.type = TYPE_PDF
val demoFile = File(context.filesDir, "demo")
demoDocumentBean.path = demoFile.listFiles()?.find { it.name.contains(".pdf") }?.absolutePath ?: ""
context.pdfCheck(demoDocumentBean)
return demoDocumentBean
}
fun getWordDemo(context: Context): DocumentBean {
val demoDocumentBean = DocumentBean()
demoDocumentBean.type = TYPE_WORD
val demoFile = File(context.filesDir, "demo")
demoDocumentBean.path = demoFile.listFiles()?.find { it.name.contains(".docx") }?.absolutePath ?: ""
return demoDocumentBean
}
fun getExcelDemo(context: Context): DocumentBean {
val demoDocumentBean = DocumentBean()
demoDocumentBean.type = TYPE_EXCEL
val demoFile = File(context.filesDir, "demo")
demoDocumentBean.path = demoFile.listFiles()?.find { it.name.contains(".xlsx") }?.absolutePath ?: ""
return demoDocumentBean
}
fun getPPtDemo(context: Context): DocumentBean {
val demoDocumentBean = DocumentBean()
demoDocumentBean.type = TYPE_PPT
val demoFile = File(context.filesDir, "demo")
demoDocumentBean.path = demoFile.listFiles()?.find { it.name.contains(".pptx") }?.absolutePath ?: ""
return demoDocumentBean
}
fun getAllDocument(context: Context): MutableList<DocumentBean> {
context.upDateDemoStore()
if (!ConstObject.haveSaveDemo) {
context.saveAssetsFile()
ConstObject.haveSaveDemo = true
}
val selectionArgs = arrayOf(
MIME_TYPE_PDF,
MIME_TYPE_DOC,
MIME_TYPE_DOCX,
MIME_TYPE_XLS,
MIME_TYPE_XLSX,
MIME_TYPE_PPT,
MIME_TYPE_PPTX,
)
val list = context.getMediaFile(selectionArgs = selectionArgs)
val documentList = list.map {
val documentBean = DocumentBean(it.path, uri = it.uri, type = getDocumentType(it))
if (documentBean.type == TYPE_PDF) {
context.pdfCheck(documentBean)
}
documentBean
}
val new = documentList.toMutableList()
val pptDemo = getPPtDemo(context)
if (File(pptDemo.path).exists()) {
new.add(0, pptDemo)
}
val excelDemo = getExcelDemo(context)
if (File(excelDemo.path).exists()) {
new.add(0, excelDemo)
}
val wordDemp = getWordDemo(context)
if (File(wordDemp.path).exists()) {
new.add(0, wordDemp)
}
val pdfDemo = getPdfDemo(context)
if (File(pdfDemo.path).exists()) {
new.add(0, pdfDemo)
}
return new
}
fun getPdfDocument(context: Context): MutableList<DocumentBean> {
if (!ConstObject.haveSaveDemo) {
context.saveAssetsFile()
ConstObject.haveSaveDemo = true
}
val selectionArgs = arrayOf(
MIME_TYPE_PDF
)
val list = context.getMediaFile(selectionArgs = selectionArgs)
val documentList = list.map {
val demoDocumentBean = DocumentBean(it.path, uri = it.uri, type = TYPE_PDF)
context.pdfCheck(demoDocumentBean)
demoDocumentBean
}
val new = documentList.toMutableList()
val pdfDemo = getPdfDemo(context)
if (File(pdfDemo.path).exists()) {
new.add(0, pdfDemo)
}
return new
}
fun getWordDocument(context: Context): MutableList<DocumentBean> {
if (!ConstObject.haveSaveDemo) {
context.saveAssetsFile()
ConstObject.haveSaveDemo = true
}
val selectionArgs = arrayOf(
MIME_TYPE_DOC,
MIME_TYPE_DOCX,
)
val list = context.getMediaFile(selectionArgs = selectionArgs)
val documentList = list.map {
DocumentBean(it.path, uri = it.uri, type = TYPE_WORD)
}
val new = documentList.toMutableList()
val wordDemo = getWordDemo(context)
if (File(wordDemo.path).exists()) {
new.add(0, wordDemo)
}
return new
}
fun getExcelDocument(context: Context): MutableList<DocumentBean> {
if (!ConstObject.haveSaveDemo) {
context.saveAssetsFile()
ConstObject.haveSaveDemo = true
}
val selectionArgs = arrayOf(
MIME_TYPE_XLS,
MIME_TYPE_XLSX,
)
val list = context.getMediaFile(selectionArgs = selectionArgs)
val documentList = list.map {
DocumentBean(it.path, uri = it.uri, type = TYPE_EXCEL)
}
val new = documentList.toMutableList()
val excelDemo = getExcelDemo(context)
if (File(excelDemo.path).exists()) {
new.add(0, excelDemo)
}
return new
}
fun getPptDocument(context: Context): MutableList<DocumentBean> {
if (!ConstObject.haveSaveDemo) {
context.saveAssetsFile()
ConstObject.haveSaveDemo = true
}
val selectionArgs = arrayOf(
MIME_TYPE_PPT,
MIME_TYPE_PPTX,
)
val list = context.getMediaFile(selectionArgs = selectionArgs)
val documentList = list.map {
DocumentBean(it.path, uri = it.uri, type = TYPE_PPT)
}
val new = documentList.toMutableList()
val pptDemo = getPPtDemo(context)
if (File(pptDemo.path).exists()) {
new.add(0, pptDemo)
}
return new
}
fun recentFilter(recentList: List<String>, documentBean: DocumentBean) {
val findLastTime = recentList.filter { it.contains(documentBean.path) }.map {
it.split("_/_")[1].toLong()
}
if (findLastTime.isNotEmpty()) {
val max = findLastTime.max()
documentBean.lastViewTime = max
}
}
fun Context.pdfCheck(pdfDocumentBean: DocumentBean) {
pdfDocumentBean.state = this.checkPdfEncryption(pdfDocumentBean.path)
}
fun getDocumentType(mediaBean: MediaBean): String {
return if (mediaBean.path.endsWith(".pdf")) {
MIME_TYPE_PDF
} else if (mediaBean.path.endsWith(".doc") || mediaBean.path.endsWith(".docx")) {
TYPE_WORD
} else if (mediaBean.path.endsWith(".xls") || mediaBean.path.endsWith(".xlsx")) {
TYPE_EXCEL
} else if (mediaBean.path.endsWith(".ppt") || mediaBean.path.endsWith(".pptx")) {
TYPE_PPT
} else {
TYPE_PPT
}
}
\ No newline at end of file
package com.base.pdfreaderallpdfreader.ui.main
import android.content.Intent
import android.graphics.Color
import android.text.Spannable
import android.text.SpannableString
import android.text.style.ForegroundColorSpan
import androidx.core.view.GravityCompat
import androidx.core.view.updatePadding
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.NavController
import androidx.navigation.findNavController
import com.base.pdfreaderallpdfreader.R
import com.base.pdfreaderallpdfreader.base.BaseActivity
import com.base.pdfreaderallpdfreader.databinding.ActivityMainBinding
import com.base.pdfreaderallpdfreader.ui.language.LanguageActivity
import com.base.pdfreaderallpdfreader.ui.search.SearchActivity
import com.base.pdfreaderallpdfreader.ui.view.MainDialog.showStoragePermission
import com.base.pdfreaderallpdfreader.utils.BarUtils
import com.base.pdfreaderallpdfreader.utils.PermissionUtils.checkStorePermission
class MainActivity : BaseActivity<ActivityMainBinding>() {
override val binding: ActivityMainBinding by lazy {
ActivityMainBinding.inflate(layoutInflater)
}
private lateinit var mainViewModel: MainViewModel
private lateinit var navController: NavController
override fun initView() {
mainViewModel = ViewModelProvider(this)[MainViewModel::class.java]
mainViewModel.initScannerLauncher(this)
mainViewModel.handleActivityGmsScanResult = { imageUri, pdfUri ->
}
BarUtils.setStatusBarLightMode(this, true)
BarUtils.setStatusBarColor(this, Color.WHITE)
binding.root.updatePadding(top = BarUtils.getStatusBarHeight())
navController = findNavController(R.id.nav_host_fragment_content_main)
val spannableString = SpannableString(this.getString(R.string.pdf_reader))
spannableString.setSpan(ForegroundColorSpan(Color.parseColor("#E20001")), 0, 3, Spannable.SPAN_INCLUSIVE_INCLUSIVE)
binding.includeMain.tvTittle.text = spannableString
binding.tvPdfReader.text = spannableString
if (!checkStorePermission()) {
showStoragePermission(launcher)
}
}
override fun initListener() {
super.initListener()
binding.includeMain.ivMenu.setOnClickListener {
binding.drawerLayout.openDrawer(GravityCompat.START)
}
binding.flFanhui.setOnClickListener {
binding.drawerLayout.closeDrawer(GravityCompat.START)
}
binding.includeMain.includeContentMain.llHome.setOnClickListener {
changeHomeUI()
}
binding.includeMain.includeContentMain.llHome.callOnClick()
binding.includeMain.includeContentMain.llRecent.setOnClickListener {
changeRecentUI()
}
binding.includeMain.includeContentMain.llBookmark.setOnClickListener {
changeBookMarkUI()
}
binding.llLanguage.setOnClickListener {
startActivity(Intent(this, LanguageActivity::class.java))
}
binding.includeMain.includeContentMain.ivScan.setOnClickListener {
starAdGmsScan()
}
binding.includeMain.ivSearch.setOnClickListener {
startActivity(Intent(this, SearchActivity::class.java))
}
}
private fun starAdGmsScan() {
// if (AdmobHelper.isShowScanInter() && AdmobHelper.canCommonShowAd()) {
// AdmobInterstitialUtils.showInterstitialAd(activity) {
// if (it) {
// lastScanShowAd = System.currentTimeMillis()
// }
// starGmsScan(activity)
// }
// } else {
mainViewModel.starGmsScan(this)
// }
}
private fun disSelectBottomNav() {
binding.includeMain.includeContentMain.ivHome.isSelected = false
binding.includeMain.includeContentMain.tvHome.isSelected = false
binding.includeMain.includeContentMain.ivRecent.isSelected = false
binding.includeMain.includeContentMain.tvRecent.isSelected = false
binding.includeMain.includeContentMain.ivBookmark.isSelected = false
binding.includeMain.includeContentMain.tvBookmark.isSelected = false
}
private fun changeBookMarkUI() {
disSelectBottomNav()
binding.includeMain.includeContentMain.ivBookmark.isSelected = true
binding.includeMain.includeContentMain.tvBookmark.isSelected = true
navController.popBackStack()
navController.navigate(R.id.nav_bookmarkFragment)
}
private fun changeRecentUI() {
disSelectBottomNav()
binding.includeMain.includeContentMain.ivRecent.isSelected = true
binding.includeMain.includeContentMain.tvRecent.isSelected = true
navController.popBackStack()
navController.navigate(R.id.nav_recentFragment)
}
private fun changeHomeUI() {
disSelectBottomNav()
binding.includeMain.includeContentMain.ivHome.isSelected = true
binding.includeMain.includeContentMain.tvHome.isSelected = true
navController.popBackStack()
navController.navigate(R.id.nav_homeFragment)
}
}
\ No newline at end of file
package com.base.pdfreaderallpdfreader.ui.main
import android.app.Activity
import android.content.IntentSender
import android.net.Uri
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.IntentSenderRequest
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.ViewModel
import com.google.mlkit.vision.documentscanner.GmsDocumentScannerOptions
import com.google.mlkit.vision.documentscanner.GmsDocumentScanning
import com.google.mlkit.vision.documentscanner.GmsDocumentScanningResult
class MainViewModel : ViewModel() {
private var scannerLauncher: ActivityResultLauncher<IntentSenderRequest>? = null
var handleActivityGmsScanResult: ((imageUri: Uri?, pdfUri: Uri?) -> Unit)? = null
private var scannerLauncherRegister: Boolean = false
fun initScannerLauncher(appCompatActivity: AppCompatActivity) {
scannerLauncher =
appCompatActivity.registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { activityResult ->
val resultCode = activityResult.resultCode
val result = GmsDocumentScanningResult.fromActivityResultIntent(activityResult.data)
// appCompatActivity.toast("回调1")
if (resultCode == Activity.RESULT_OK && result != null) {
val pages = result.pages
// appCompatActivity.toast("回调2 ${pages?.size}")
var imageUri = Uri.EMPTY
if (!pages.isNullOrEmpty()) {
// appCompatActivity.toast("回调3")
imageUri = pages[0].imageUri
}
val pdfUri = result.pdf?.uri ?: Uri.EMPTY
handleActivityGmsScanResult?.invoke(imageUri, pdfUri)
} else {
handleActivityGmsScanResult?.invoke(null, null)
}
}
scannerLauncherRegister = true
}
fun starGmsScan(activity: Activity) {
runCatching {
if (scannerLauncher == null && !scannerLauncherRegister) return
val options =
GmsDocumentScannerOptions.Builder()
.setScannerMode(GmsDocumentScannerOptions.SCANNER_MODE_BASE)
.setResultFormats(GmsDocumentScannerOptions.RESULT_FORMAT_PDF)
.setGalleryImportAllowed(true)
options.setScannerMode(GmsDocumentScannerOptions.SCANNER_MODE_FULL)
val pageLimit = 1
options.setPageLimit(pageLimit)
GmsDocumentScanning.getClient(options.build())
.getStartScanIntent(activity)
.addOnSuccessListener { intentSender: IntentSender ->
scannerLauncher?.launch(IntentSenderRequest.Builder(intentSender).build())
}
.addOnFailureListener { e: Exception ->
}
}
}
}
\ No newline at end of file
package com.base.pdfreaderallpdfreader.ui.main
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.base.pdfreaderallpdfreader.R
class PermissionFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_permission, container, false)
}
companion object {
}
}
\ No newline at end of file
package com.base.pdfreaderallpdfreader.ui.main.bookmark
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import com.base.pdfreaderallpdfreader.databinding.FragmentBookmarkBinding
import com.base.pdfreaderallpdfreader.ui.main.DocumentAdapter
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class BookmarkFragment : Fragment() {
private var _binding: FragmentBookmarkBinding? = null
// onDestroyView.
private val binding get() = _binding!!
private lateinit var bookmarkViewModel: BookmarkViewModel
private var adapter: DocumentAdapter? = null
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
bookmarkViewModel = ViewModelProvider(this)[BookmarkViewModel::class.java]
_binding = FragmentBookmarkBinding.inflate(inflater, container, false)
val root: View = binding.root
return root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
adapter = DocumentAdapter()
binding.rv.adapter = adapter
}
override fun onResume() {
super.onResume()
initData()
}
private fun initData() {
binding.swipeRefreshLayout.isRefreshing = true
lifecycleScope.launch(Dispatchers.IO) {
val recentList = bookmarkViewModel.getBookmarkDocument(requireContext())
launch(Dispatchers.Main) {
if (recentList.isEmpty()) {
binding.llEmpty.visibility = View.VISIBLE
adapter?.submitList(listOf())
} else {
binding.llEmpty.visibility = View.GONE
adapter?.submitList(recentList)
}
binding.swipeRefreshLayout.isRefreshing = false
}
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
\ No newline at end of file
package com.base.pdfreaderallpdfreader.ui.main.bookmark
import android.content.Context
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.base.pdfreaderallpdfreader.bean.DocumentBean
import com.base.pdfreaderallpdfreader.bean.DocumentBean.Companion.TYPE_PDF
import com.base.pdfreaderallpdfreader.ui.main.getAllDocument
import com.base.pdfreaderallpdfreader.ui.main.pdfCheck
import com.base.pdfreaderallpdfreader.utils.SpStringUtils
import com.base.pdfreaderallpdfreader.utils.SpStringUtils.BOOKMARK_KEY
class BookmarkViewModel : ViewModel() {
private val _text = MutableLiveData<String>().apply {
value = "This is gallery Fragment"
}
val text: LiveData<String> = _text
fun getBookmarkDocument(context: Context): List<DocumentBean> {
val all = getAllDocument(context)
val bookmarkList = SpStringUtils.getSpStringList(BOOKMARK_KEY)
all.map {
if (it.type == TYPE_PDF) {
context.pdfCheck(it)
}
it.isBookmarked = bookmarkList.contains(it.path)
}
return all.filter { it.isBookmarked }
}
}
\ No newline at end of file
package com.base.pdfreaderallpdfreader.ui.main.home
import android.content.Intent
import android.graphics.Color
import android.os.Bundle
import android.text.Spannable
import android.text.SpannableString
import android.text.style.ForegroundColorSpan
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import com.base.pdfreaderallpdfreader.R
import com.base.pdfreaderallpdfreader.databinding.FragmentHomeBinding
import com.base.pdfreaderallpdfreader.ui.document.DocumentActivity
class HomeFragment : Fragment() {
private var _binding: FragmentHomeBinding? = null
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
val homeViewModel =
ViewModelProvider(this).get(HomeViewModel::class.java)
_binding = FragmentHomeBinding.inflate(inflater, container, false)
val root: View = binding.root
return root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.clPdfReader.setOnClickListener {
startActivity(Intent(requireContext(), DocumentActivity::class.java))
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
\ No newline at end of file
package com.base.pdfreaderallpdfreader.ui.main.home
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
class HomeViewModel : ViewModel() {
private val _text = MutableLiveData<String>().apply {
value = "This is home Fragment"
}
val text: LiveData<String> = _text
}
\ No newline at end of file
package com.base.pdfreaderallpdfreader.ui.main.recent
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import com.base.pdfreaderallpdfreader.databinding.FragmentRecentBinding
import com.base.pdfreaderallpdfreader.ui.main.DocumentAdapter
import com.base.pdfreaderallpdfreader.utils.LogEx
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlin.random.Random
class RecentFragment() : Fragment() {
private val TAG = "RecentFragment"
private var _binding: FragmentRecentBinding? = null
private val binding get() = _binding!!
private lateinit var recentViewModel: RecentViewModel
private var adapter: DocumentAdapter? = null
var i = Random(100).nextInt()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
LogEx.logDebug(TAG, "onCreate $i")
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
recentViewModel = ViewModelProvider(this)[RecentViewModel::class.java]
_binding = FragmentRecentBinding.inflate(inflater, container, false)
val root: View = binding.root
return root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
adapter = DocumentAdapter()
binding.rv.adapter = adapter
}
override fun onResume() {
super.onResume()
initData()
}
private fun initData() {
// if (!recentNeedRefresh) return
// recentNeedRefresh = false
binding.swipeRefreshLayout.isRefreshing = true
lifecycleScope.launch(Dispatchers.IO) {
val recentList = recentViewModel.getRecentDocument(requireContext())
launch(Dispatchers.Main) {
if (recentList.isEmpty()) {
binding.llEmpty.visibility = View.VISIBLE
adapter?.submitList(listOf())
} else {
binding.llEmpty.visibility = View.GONE
adapter?.submitList(recentList)
}
binding.swipeRefreshLayout.isRefreshing = false
}
}
}
companion object {
var recentNeedRefresh = true
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
LogEx.logDebug(TAG, "onDestroyView $i")
}
override fun onDestroy() {
super.onDestroy()
LogEx.logDebug(TAG, "onDestroy $i")
}
}
\ No newline at end of file
package com.base.pdfreaderallpdfreader.ui.main.recent
import android.content.Context
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.base.pdfreaderallpdfreader.bean.DocumentBean
import com.base.pdfreaderallpdfreader.bean.DocumentBean.Companion.TYPE_PDF
import com.base.pdfreaderallpdfreader.ui.main.getAllDocument
import com.base.pdfreaderallpdfreader.ui.main.pdfCheck
import com.base.pdfreaderallpdfreader.ui.main.recentFilter
import com.base.pdfreaderallpdfreader.utils.SpStringUtils
import com.base.pdfreaderallpdfreader.utils.SpStringUtils.LAST_VIEW_KEY
class RecentViewModel : ViewModel() {
private val _text = MutableLiveData<String>().apply {
value = "This is home Fragment"
}
val text: LiveData<String> = _text
fun getRecentDocument(context: Context): List<DocumentBean> {
val all = getAllDocument(context)
val recentList = SpStringUtils.getSpStringList(LAST_VIEW_KEY)
all.forEach {
if (it.type == TYPE_PDF) {
context.pdfCheck(it)
}
recentFilter(recentList, it)
}
return all.filter { it.lastViewTime != 0L }.sortedByDescending { it.lastViewTime }
}
}
\ No newline at end of file
package com.base.pdfreaderallpdfreader.ui.search
import android.graphics.Color
import android.view.View
import android.view.inputmethod.EditorInfo
import androidx.activity.addCallback
import androidx.core.view.updatePadding
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import com.base.pdfreaderallpdfreader.base.BaseActivity
import com.base.pdfreaderallpdfreader.databinding.ActivitySearchBinding
import com.base.pdfreaderallpdfreader.databinding.ItemTabDocumentBinding
import com.base.pdfreaderallpdfreader.ui.main.DocumentAdapter
import com.base.pdfreaderallpdfreader.utils.BarUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class SearchActivity : BaseActivity<ActivitySearchBinding>() {
private lateinit var searchViewModel: SearchViewModel
private var adapter: DocumentAdapter? = null
override val binding: ActivitySearchBinding by lazy {
ActivitySearchBinding.inflate(layoutInflater)
}
override fun initView() {
BarUtils.setStatusBarLightMode(this, true)
BarUtils.setStatusBarColor(this, Color.WHITE)
binding.root.updatePadding(top = BarUtils.getStatusBarHeight())
searchViewModel = ViewModelProvider(this)[SearchViewModel::class.java]
adapter = DocumentAdapter()
binding.rv.adapter = adapter
arrayOf("All", "PDF", "Word", "Excel", "PPT").forEach { tab ->
val tabBinding = ItemTabDocumentBinding.inflate(layoutInflater)
tabBinding.tv.text = tab
binding.tabLayout.addView(tabBinding.root)
}
binding.tabLayout.observeIndexChange { fromIndex, toIndex, reselect, fromUser ->
if (!reselect) {
when (toIndex) {
0 -> searchViewModel.searchMode = SEARCH_MODE_ALL
1 -> searchViewModel.searchMode = SEARCH_MODE_PDF
2 -> searchViewModel.searchMode = SEARCH_MODE_WORD
3 -> searchViewModel.searchMode = SEARCH_MODE_EXCEL
4 -> searchViewModel.searchMode = SEARCH_MODE_PPT
}
searchDocument()
}
}
binding.edit.setOnEditorActionListener { v, actionId, event ->
if (actionId == EditorInfo.IME_ACTION_DONE) {
if (binding.edit.text.isNotEmpty()) {
searchDocument()
}
}
false
}
searchDocument()
}
override fun initListener() {
super.initListener()
onBackPressedDispatcher.addCallback {
finishToMain()
}
binding.flFanhui.setOnClickListener {
onBackPressedDispatcher.onBackPressed()
}
}
private fun searchDocument() {
val search = binding.edit.text.toString()
lifecycleScope.launch(Dispatchers.IO) {
val result = searchViewModel.getSearchDocument(this@SearchActivity, search)
launch(Dispatchers.Main) {
if (result.isEmpty()) {
binding.llEmpty.visibility = View.VISIBLE
adapter?.submitList(listOf())
} else {
binding.llEmpty.visibility = View.GONE
adapter?.submitList(result)
}
}
}
}
companion object {
var SEARCH_MODE_ALL = "search_mode_all"
var SEARCH_MODE_PDF = "search_mode_pdf"
var SEARCH_MODE_WORD = "search_mode_word"
var SEARCH_MODE_EXCEL = "search_mode_excel"
var SEARCH_MODE_PPT = "search_mode_ppt"
}
}
\ No newline at end of file
package com.base.pdfreaderallpdfreader.ui.search
import android.content.Context
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.base.pdfreaderallpdfreader.bean.DocumentBean
import com.base.pdfreaderallpdfreader.bean.DocumentBean.Companion.TYPE_EXCEL
import com.base.pdfreaderallpdfreader.bean.DocumentBean.Companion.TYPE_PDF
import com.base.pdfreaderallpdfreader.bean.DocumentBean.Companion.TYPE_PPT
import com.base.pdfreaderallpdfreader.bean.DocumentBean.Companion.TYPE_WORD
import com.base.pdfreaderallpdfreader.ui.main.getAllDocument
import com.base.pdfreaderallpdfreader.ui.search.SearchActivity.Companion.SEARCH_MODE_ALL
import com.base.pdfreaderallpdfreader.ui.search.SearchActivity.Companion.SEARCH_MODE_EXCEL
import com.base.pdfreaderallpdfreader.ui.search.SearchActivity.Companion.SEARCH_MODE_PDF
import com.base.pdfreaderallpdfreader.ui.search.SearchActivity.Companion.SEARCH_MODE_PPT
import com.base.pdfreaderallpdfreader.ui.search.SearchActivity.Companion.SEARCH_MODE_WORD
import java.io.File
import java.util.Locale
class SearchViewModel : ViewModel() {
var searchMode = SEARCH_MODE_ALL
fun getSearchDocument(context: Context, search: String): List<DocumentBean> {
val all = getAllDocument(context)
val typeList: List<DocumentBean>
when (searchMode) {
SEARCH_MODE_PDF -> {
typeList = all.filter { it.type == TYPE_PDF }
}
SEARCH_MODE_WORD -> {
typeList = all.filter { it.type == TYPE_WORD }
}
SEARCH_MODE_EXCEL -> {
typeList = all.filter { it.type == TYPE_EXCEL }
}
SEARCH_MODE_PPT -> {
typeList = all.filter { it.type == TYPE_PPT }
}
else -> typeList = all
}
typeList.filter {
File(it.path).name.lowercase(Locale.ENGLISH)
.contains(search.lowercase(Locale.ENGLISH))
}
return typeList
}
}
\ No newline at end of file
package com.base.pdfreaderallpdfreader.ui.splash
import android.annotation.SuppressLint
import android.content.Intent
import com.base.pdfreaderallpdfreader.base.BaseActivity
import com.base.pdfreaderallpdfreader.databinding.ActivitySplashBinding
import com.base.pdfreaderallpdfreader.ui.main.MainActivity
@SuppressLint("CustomSplashScreen")
class SplashActivity : BaseActivity<ActivitySplashBinding>() {
override val binding: ActivitySplashBinding by lazy {
ActivitySplashBinding.inflate(layoutInflater)
}
override fun initView() {
startActivity(Intent(this, MainActivity::class.java))
}
}
\ No newline at end of file
package com.base.pdfreaderallpdfreader.ui.view
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import com.base.pdfreaderallpdfreader.R
import com.base.pdfreaderallpdfreader.databinding.DialogStoragePermissionBinding
import com.base.pdfreaderallpdfreader.utils.ActivityLauncher
import com.base.pdfreaderallpdfreader.utils.PermissionUtils.requestStoragePermission
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog
object MainDialog {
fun Context.showStoragePermission(
launcher: ActivityLauncher,
launcherAction: ((flag: Boolean) -> Unit)? = null,
noLauncherAction: (() -> Unit)? = null,
dismissAction: (() -> Unit)? = null,
): BottomSheetDialog {
val dialog = BottomSheetDialog(this, R.style.BottomSheetDialog)
val binding = DialogStoragePermissionBinding.inflate(LayoutInflater.from(this))
dialog.setContentView(binding.root)
dialog.setCanceledOnTouchOutside(true)
dialog.show()
val parentView = binding.root.parent as View
val behavior = BottomSheetBehavior.from(parentView)
//展开
behavior.state = BottomSheetBehavior.STATE_EXPANDED
binding.tvAllow.setOnClickListener {
dialog.dismiss()
requestStoragePermission(launcher) {
launcherAction?.invoke(it)
}
}
dialog.setOnDismissListener {
dismissAction?.invoke()
}
return dialog
}
}
\ No newline at end of file
package com.base.pdfreaderallpdfreader.utils
import android.content.Intent
import androidx.activity.result.ActivityResult
import androidx.activity.result.ActivityResultCallback
import androidx.activity.result.ActivityResultCaller
import androidx.activity.result.contract.ActivityResultContracts
class ActivityLauncher(activityResultCaller: ActivityResultCaller) {
//region 权限
private var permissionCallback: ActivityResultCallback<Map<String, Boolean>>? = null
private val permissionLauncher =
activityResultCaller.registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { result: Map<String, Boolean> ->
permissionCallback?.onActivityResult(result)
}
fun launch(
permissionArray: Array<String>,
permissionCallback: ActivityResultCallback<Map<String, Boolean>>?
) {
this.permissionCallback = permissionCallback
permissionLauncher.launch(permissionArray)
}
//endregion
//region intent跳转
private var activityResultCallback: ActivityResultCallback<ActivityResult>? = null
private val intentLauncher =
activityResultCaller.registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { activityResult: ActivityResult ->
activityResultCallback?.onActivityResult(activityResult)
}
/**
* it.resultCode == Activity.RESULT_OK
*/
fun launch(
intent: Intent,
activityResultCallback: ActivityResultCallback<ActivityResult>? = null
) {
this.activityResultCallback = activityResultCallback
intentLauncher.launch(intent)
}
//endregion
//region saf
// private var safResultCallback: ActivityResultCallback<Uri?>? = null
// private val safLauncher =
// activityResultCaller.registerForActivityResult(
// ActivityResultContracts.OpenDocument(),
// ) { uri ->
// safResultCallback?.onActivityResult(uri)
// }
//
// fun launch(array: Array<String>, safResultCallback: ActivityResultCallback<Uri?>?) {
// this.safResultCallback = safResultCallback
// safLauncher.launch(array)
// }
//end region
}
\ No newline at end of file
package com.base.pdfreaderallpdfreader.utils;
import android.app.Activity;
import java.util.Stack;
public class ActivityManagerUtils {
private static ActivityManagerUtils instance;
private Stack<Activity> activityStack = new Stack<>();
private ActivityManagerUtils() {
}
public static ActivityManagerUtils getInstance() {
if (instance == null) {
instance = new ActivityManagerUtils();
}
return instance;
}
/**
* 添加Activity到堆栈
*/
public void addActivity(Activity activity) {
activityStack.add(activity);
}
/**
* 移除Activity从堆栈
*/
public void removeActivity(Activity activity) {
activityStack.remove(activity);
}
/**
* 获取当前Activity(堆栈中最后一个压入的)
*/
public Activity getCurrentActivity() {
return activityStack.lastElement();
}
/**
* 结束指定的Activity
*/
public void finishActivity(Activity activity) {
if (activity != null) {
activityStack.remove(activity);
activity.finish();
}
}
/**
* 结束所有Activity
*/
public void finishAllActivity() {
for (Activity activity : activityStack) {
if (activity != null) {
activity.finish();
}
}
activityStack.clear();
}
/**
* 检查Activity是否存在于堆栈中
*/
public boolean isActivityInStack(Class<?> cls) {
boolean isExist = false;
if (cls != null) {
for (Activity activity : activityStack) {
if (cls.equals(activity.getClass())) {
isExist = true;
break;
}
}
}
return isExist;
}
public Activity getTopActivity() {
if (activityStack.empty()) {
return null;
} else {
return activityStack.peek();
}
}
}
\ No newline at end of file
package com.base.pdfreaderallpdfreader.utils;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import com.base.pdfreaderallpdfreader.helper.MyApplication;
import java.util.Set;
/**
* @noinspection ALL, rawtypes, rawtypes
*/
public class AppPreferences {
private static AppPreferences sInstance;
private final SharedPreferences sharedPreferences;
private static final String PREF_FILE_NAME = "app_prefs"; // 偏好文件名
private AppPreferences(Context context) {
sharedPreferences = context.getSharedPreferences(PREF_FILE_NAME, Context.MODE_PRIVATE);
}
public static synchronized AppPreferences getInstance() {
if (sInstance == null) {
sInstance = new AppPreferences(MyApplication.context.getApplicationContext());
}
return sInstance;
}
// 通用 put 方法
public void put(String key, Object value) {
if (value instanceof Integer) {
sharedPreferences.edit().putInt(key, (Integer) value).apply();
} else if (value instanceof Long) {
sharedPreferences.edit().putLong(key, (Long) value).apply();
} else if (value instanceof Float) {
sharedPreferences.edit().putFloat(key, (Float) value).apply();
} else if (value instanceof Boolean) {
sharedPreferences.edit().putBoolean(key, (Boolean) value).apply();
} else if (value instanceof String) {
sharedPreferences.edit().putString(key, (String) value).apply();
} else if (value instanceof Double) {
sharedPreferences.edit().putString(key, (String) value.toString()).apply();
} else if (value instanceof Set) {
sharedPreferences.edit().putStringSet(key, (Set<String>) value).apply();
} else {
throw new IllegalArgumentException("Unsupported type: " + value.getClass());
}
}
@SuppressLint("ApplySharedPref")
public void put(String key, Object value, boolean isCommit) {
SharedPreferences.Editor editor = sharedPreferences.edit();
if (value instanceof Integer) {
editor.putInt(key, (Integer) value);
} else if (value instanceof Long) {
editor.putLong(key, (Long) value);
} else if (value instanceof Float) {
editor.putFloat(key, (Float) value);
} else if (value instanceof Boolean) {
editor.putBoolean(key, (Boolean) value);
} else if (value instanceof String) {
editor.putString(key, (String) value);
} else if (value instanceof Set) {
sharedPreferences.edit().putStringSet(key, (Set<String>) value).apply();
} else {
throw new IllegalArgumentException("Unsupported type: " + value.getClass());
}
// 根据 isCommit 参数的值决定使用 commit() 还是 apply()
if (isCommit) {
editor.commit();
} else {
editor.apply();
}
}
// 存入整数
public void putInt(String key, int value) {
sharedPreferences.edit().putInt(key, value).apply();
}
public void putStringSet(String key, Set value) {
sharedPreferences.edit().putStringSet(key, value).apply();
}
public Set<String> getStringSet(String key, Set<String> defaultValue) {
return sharedPreferences.getStringSet(key, defaultValue);
}
// 获取整数
public int getInt(String key, int defaultValue) {
return sharedPreferences.getInt(key, defaultValue);
}
// 存入长整数
public void putLong(String key, long value) {
sharedPreferences.edit().putLong(key, value).apply();
}
// 获取长整数
public long getLong(String key, long defaultValue) {
return sharedPreferences.getLong(key, defaultValue);
}
// 存入浮点数
public void putFloat(String key, float value) {
sharedPreferences.edit().putFloat(key, value).apply();
}
// 获取浮点数
public float getFloat(String key, float defaultValue) {
return sharedPreferences.getFloat(key, defaultValue);
}
// 存入布尔值
public void putBoolean(String key, boolean value) {
sharedPreferences.edit().putBoolean(key, value).apply();
}
// 获取布尔值
public boolean getBoolean(String key, boolean defaultValue) {
return sharedPreferences.getBoolean(key, defaultValue);
}
// 存入字符串
public void putString(String key, String value) {
sharedPreferences.edit().putString(key, value).apply();
}
// 获取字符串
public String getString(String key, String defaultValue) {
return sharedPreferences.getString(key, defaultValue);
}
// 检查某个键是否存在
public boolean contains(String key) {
return sharedPreferences.contains(key);
}
// 移除某个键
public void remove(String key) {
sharedPreferences.edit().remove(key).apply();
}
// 清除所有数据
public void clear() {
sharedPreferences.edit().clear().apply();
}
}
\ No newline at end of file
package com.base.pdfreaderallpdfreader.utils
import android.content.Context
import android.content.res.AssetManager
import java.io.BufferedReader
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.io.InputStream
import java.io.InputStreamReader
object AssetUtils {
fun Context.readByteArrayFromAsset(fileName: String): ByteArray {
val assetManager: AssetManager = this.assets
var ins: InputStream? = null
val byteStream = ByteArrayOutputStream()
try {
ins = assetManager.open(fileName)
var nextValue: Int
while (ins.read().also { nextValue = it } != -1) {
byteStream.write(nextValue)
}
} catch (e: IOException) {
e.printStackTrace()
} finally {
try {
ins?.close()
byteStream.close()
} catch (e: IOException) {
e.printStackTrace()
}
}
return byteStream.toByteArray()
}
fun Context.getDemoPdf(): String {
val demoFile = File(filesDir, "demo")
demoFile.mkdirs()
val file = File(demoFile, "DEMO.pdf")
return file.absolutePath
}
fun Context.getDemoDocx(): String {
val demoFile = File(filesDir, "demo")
demoFile.mkdirs()
val file = File(demoFile, "DEMO.docx")
return file.absolutePath
}
fun Context.getDemoXlsx(): String {
val demoFile = File(filesDir, "demo")
demoFile.mkdirs()
val file = File(demoFile, "DEMO.xlsx")
return file.absolutePath
}
fun Context.getDemoPptx(): String {
val demoFile = File(filesDir, "demo")
demoFile.mkdirs()
val file = File(demoFile, "DEMO.pptx")
return file.absolutePath
}
fun Context.saveAssetsFile() {
val demoFile = File(filesDir, "demo")
demoFile.mkdirs()
arrayOf(
"DEMO.pdf",
"DEMO.docx",
"DEMO.xlsx",
"DEMO.pptx"
).forEach {
val file = File(demoFile, it)
if (file.exists() && file.length() != 0L) {
return
}
file.createNewFile()
try {
FileOutputStream(file).use { fos -> fos.write(readByteArrayFromAsset(it)) }
} catch (e: IOException) {
e.printStackTrace()
}
}
}
fun Context.readJsonFromAsset(fileName: String): String {
var json = ""
try {
val assetManager = this.assets
val inputStream = assetManager.open(fileName)
val reader = BufferedReader(InputStreamReader(inputStream))
var line: String?
val jsonString = StringBuilder()
while (reader.readLine().also { line = it } != null) {
jsonString.append(line)
}
reader.close()
inputStream.close()
json = jsonString.toString()
} catch (e: IOException) {
e.printStackTrace()
}
return json
}
}
\ No newline at end of file
package com.base.pdfreaderallpdfreader.utils
//noinspection SuspiciousImport
import android.app.Activity
import android.content.Context
import android.content.res.Resources
import android.graphics.Color
import android.os.Build
import android.view.View
import android.view.ViewGroup
import android.view.Window
import android.view.WindowManager
import androidx.annotation.ColorInt
object BarUtils {
fun setStatusBarLightMode(activity: Activity, isLightMode: Boolean) {
setStatusBarLightMode(activity.window, isLightMode)
}
private fun setStatusBarLightMode(window: Window, isLightMode: Boolean) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val decorView = window.decorView
var vis = decorView.systemUiVisibility
vis = if (isLightMode) {
vis or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
} else {
vis and View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.inv()
}
decorView.systemUiVisibility = vis
}
}
fun setStatusBarColor(activity: Activity, @ColorInt color: Int): View? {
return setStatusBarColor(activity, color, false)
}
private fun setStatusBarColor(activity: Activity, @ColorInt color: Int, isDecor: Boolean): View? {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return null
transparentStatusBar(activity)
return applyStatusBarColor(activity, color, isDecor)
}
private fun applyStatusBarColor(activity: Activity, color: Int, isDecor: Boolean): View {
return applyStatusBarColor(activity.window, color, isDecor)
}
private fun transparentStatusBar(activity: Activity) {
transparentStatusBar(activity.window)
}
private fun transparentStatusBar(window: Window) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
val option = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
val vis = window.decorView.systemUiVisibility
window.decorView.systemUiVisibility = option or vis
window.statusBarColor = Color.TRANSPARENT
} else {
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
}
}
private fun applyStatusBarColor(window: Window, color: Int, isDecor: Boolean): View {
val parent =
if (isDecor) window.decorView as ViewGroup else (window.findViewById<View>(android.R.id.content) as ViewGroup)!!
var fakeStatusBarView =
parent.findViewWithTag<View>(TAG_STATUS_BAR)
if (fakeStatusBarView != null) {
if (fakeStatusBarView.visibility == View.GONE) {
fakeStatusBarView.visibility = View.VISIBLE
}
fakeStatusBarView.setBackgroundColor(color)
} else {
fakeStatusBarView = createStatusBarView(window.context, color)
parent.addView(fakeStatusBarView)
}
return fakeStatusBarView
}
private fun createStatusBarView(context: Context, color: Int): View {
val statusBarView = View(context)
statusBarView.layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight()
)
statusBarView.setBackgroundColor(color)
statusBarView.tag = TAG_STATUS_BAR
return statusBarView
}
///////////////////////////////////////////////////////////////////////////
// status bar
///////////////////////////////////////////////////////////////////////////
private const val TAG_STATUS_BAR = "TAG_STATUS_BAR"
fun getStatusBarHeight(): Int {
val resources = Resources.getSystem()
val resourceId = resources.getIdentifier("status_bar_height", "dimen", "android")
return resources.getDimensionPixelSize(resourceId)
}
}
\ No newline at end of file
package com.base.pdfreaderallpdfreader.utils
import java.text.SimpleDateFormat
import java.util.Locale
object KotlinExt {
fun Number.toFormatSize(count: Int = 1): String {
var suffix = "B"
var fSize = this.toDouble()
if (fSize > 1024) {
suffix = "KB"
fSize /= 1024.0
}
if (fSize > 1024) {
suffix = "MB"
fSize /= 1024.0
}
if (fSize > 1024) {
suffix = "GB"
fSize /= 1024.0
}
return String.format("%.${count}f %s", fSize, suffix)
}
fun Long.toFormatTime(): String {
return SimpleDateFormat("MMM dd,yyyy", Locale.ENGLISH).format(this)
}
fun Long.toFormatTime2(): String {
return SimpleDateFormat("yyyyMMdd_HHmmss", Locale.ENGLISH).format(this)
}
fun Long.toFormatTime3(): String {
return SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH).format(this)
}
fun Long.toFormatTime4(): String {
return SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH).format(this)
}
fun Long.toFormatTime5(): String {
return SimpleDateFormat("dd-MM-yyyy", Locale.ENGLISH).format(this)
}
fun Long.toFormatMinute(): String {
return SimpleDateFormat("mm", Locale.ENGLISH).format(this)
}
fun Array<String>.array2String(): String {
val stringBuilder = StringBuilder()
forEach {
stringBuilder.append(it)
}
return stringBuilder.toString()
}
}
\ No newline at end of file
package com.base.pdfreaderallpdfreader.utils
import android.content.Context
import android.os.LocaleList
import java.util.Locale
object LanguageUtils {
fun getSystemLanguage(): String {
return Locale.getDefault().language
}
val supportLanguage = listOf(
Locale.ENGLISH.language,
Locale.PRC.language,
Locale("pt", "BR").language,
Locale("es").language,
Locale.FRENCH.language,
Locale("de").language,
Locale("th", "TH").language,
Locale("in", "ID").language,
Locale("ms", "MY").language,
Locale("vi", "VN").language,
Locale("ja", "JP").language,
Locale("it", "IT").language,
Locale("ko", "KR").language,
Locale("nl", "NL").language,
Locale("zh", "TW").language,
Locale("tr", "TR").language
)
fun getSystemLanguageDefault(): String {
var systemLanguage = getSystemLanguage()
if (!supportLanguage.contains(systemLanguage)) {
systemLanguage = Locale.ENGLISH.language
}
return systemLanguage
}
fun isSupportSystemLanguage(): Boolean {
return supportLanguage.contains(getSystemLanguage())
}
fun changeAppLanguage(context: Context,language:String) {
val config = context.resources.configuration
val locale = Locale(language)
//Android 7.0以上的方法
config.setLocale(locale)
config.setLocales(LocaleList(locale))
context.createConfigurationContext(config)
context.resources.updateConfiguration(config, context.resources.displayMetrics)
}
}
\ No newline at end of file
package com.base.pdfreaderallpdfreader.utils
import android.util.Log
object LogEx {
val isOpen = true
val filterTAG = arrayOf(
"",
"MediaStoreUtils",
"DocumentFragment",
"EventUtils",
"ReportUtils",
// "NewComUtils",
)
fun logDebug(tag: String, content: String, isMust: Boolean = false) {
if (isMust) {
Log.e(tag, content)
} else {
if (!isOpen) return
if (filterTAG.contains(tag)) return
// if (BuildConfig.DEBUG) {
Log.e(tag, content)
// }
}
}
}
\ No newline at end of file
package com.base.pdfreaderallpdfreader.utils
import android.annotation.SuppressLint
import android.content.Context
import android.database.Cursor
import android.media.MediaScannerConnection
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.DocumentsContract
import android.provider.MediaStore
import android.provider.OpenableColumns
import com.base.pdfreaderallpdfreader.bean.ConstObject.MIME_TYPE_APK
import com.base.pdfreaderallpdfreader.bean.ConstObject.MIME_TYPE_DOC
import com.base.pdfreaderallpdfreader.bean.ConstObject.MIME_TYPE_DOCX
import com.base.pdfreaderallpdfreader.bean.ConstObject.MIME_TYPE_PDF
import com.base.pdfreaderallpdfreader.bean.ConstObject.MIME_TYPE_PPT
import com.base.pdfreaderallpdfreader.bean.ConstObject.MIME_TYPE_PPTX
import com.base.pdfreaderallpdfreader.bean.ConstObject.MIME_TYPE_XLS
import com.base.pdfreaderallpdfreader.bean.ConstObject.MIME_TYPE_XLSX
import com.base.pdfreaderallpdfreader.bean.ConstObject.MIME_TYPE_ZIP
import com.base.pdfreaderallpdfreader.bean.MediaBean
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableSharedFlow
import java.io.File
private val TAG = "MediaStoreUtils"
private val commonMediaDir = arrayOf(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).absolutePath,
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).absolutePath,
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).absolutePath,
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES).absolutePath,
)
fun Context.updateMediaStore(
filePath: Array<String> = commonMediaDir
) {
MediaScannerConnection.scanFile(
this, filePath, null
) { path: String?, uri: Uri? -> }
}
fun Context.upDateDemoStore() {
val demoFile = File(filesDir, "demo")
MediaScannerConnection.scanFile(
this, arrayOf(demoFile.absolutePath) , null
) { path: String?, uri: Uri? -> }
}
//图片视频音频不用这个查
fun Context.getMediaFile(selectionArgs: Array<String>? = null): ArrayList<MediaBean> {
val list = arrayListOf<MediaBean>()
val projection = arrayOf(
MediaStore.Files.FileColumns._ID,
MediaStore.Files.FileColumns.DATA,
// MediaStore.Files.FileColumns.TITLE,
MediaStore.Files.FileColumns.MIME_TYPE,
// MediaStore.Files.FileColumns.SIZE,
)
val mimeTypeSelectionArgs = selectionArgs ?: arrayOf(
MIME_TYPE_PDF,
MIME_TYPE_DOC,
MIME_TYPE_DOCX,
MIME_TYPE_XLS,
MIME_TYPE_XLSX,
MIME_TYPE_PPT,
MIME_TYPE_PPTX,
MIME_TYPE_APK
)
val mimeTypeSelection = if (mimeTypeSelectionArgs.size == 1) {
"${MediaStore.Files.FileColumns.MIME_TYPE} = ?"
} else {
"${MediaStore.Files.FileColumns.MIME_TYPE} IN (" + mimeTypeSelectionArgs.joinToString(",") { "?" } + ")"
}
// val selection = "$timeSelection AND $mimeTypeSelection"
val selection = mimeTypeSelection
LogEx.logDebug(TAG, "selection=$selection")
var cursor: Cursor? = null
try {
// 进行查询,并设置排序方式,按照文件添加时间降序排序
cursor = this.contentResolver.query(
MediaStore.Files.getContentUri("external"),
projection,
selection,
selectionArgs ?: mimeTypeSelectionArgs,
MediaStore.Files.FileColumns.DATE_ADDED + " DESC"
)
if (cursor != null) {
while (cursor.moveToNext()) {
runCatching {
val id = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns._ID))
val uri = Uri.withAppendedPath(MediaStore.Files.getContentUri("external"), id.toString())
val path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DATA))
// val title = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.TITLE))
val mimeType = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.MIME_TYPE))
// val size = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.SIZE))
LogEx.logDebug(TAG, "path=$path uri=$uri mimeType=$mimeType")
list.add(
MediaBean(path = path, uri = uri, mimeType = mimeType)
)
}
}
}
} catch (e: Exception) {
LogEx.logDebug(TAG, "Exception $e")
} finally {
cursor?.close()
}
return list
}
@SuppressLint("Range")
fun Context.getMediaPhotoCountSize(): Pair<Int, Long> {
var count = 0
var totalSize = 0L
runCatching {
val contentResolver = this.contentResolver
// 定义查询的Uri和列
val uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
val projection = arrayOf(MediaStore.Images.Media._ID, MediaStore.Images.Media.SIZE)
// 执行查询
val cursor = contentResolver.query(uri, projection, null, null, null)
// 检查cursor是否包含数据
count = cursor?.count ?: 0
while (cursor?.moveToNext() == true) {
totalSize += cursor.getInt(cursor.getColumnIndex(MediaStore.Video.Media.SIZE))
}
// 关闭cursor
cursor?.close()
}
return Pair(count, totalSize)
}
fun Context.getMediaPhoto(): List<MediaBean> {
val list = arrayListOf<MediaBean>()
val contentResolver = this.contentResolver
// 定义查询的Uri和列
val baseUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
val projection = arrayOf(MediaStore.Images.Media._ID, MediaStore.Images.Media.DATA)
// 执行查询
var cursor: Cursor? = null
try {
cursor = contentResolver.query(baseUri, projection, null, null, null)
if (cursor != null) {
while (cursor.moveToNext()) {
val id = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID))
val uri = Uri.withAppendedPath(baseUri, id.toString())
val path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA))
list.add(MediaBean(path = path, uri = uri, mimeType = "image/*"))
}
}
} catch (e: Exception) {
} finally {
cursor?.close()
}
return list
}
fun Context.getMediaVideo(): List<MediaBean> {
val list = arrayListOf<MediaBean>()
val contentResolver = this.contentResolver
// 定义查询的Uri和列
val baseUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI
val projection = arrayOf(MediaStore.Video.Media._ID, MediaStore.Video.Media.DATA, MediaStore.Video.Media.MIME_TYPE)
// 执行查询
var cursor: Cursor? = null
try {
cursor = contentResolver.query(baseUri, projection, null, null, null)
if (cursor != null) {
while (cursor.moveToNext()) {
val id = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID))
val uri = Uri.withAppendedPath(baseUri, id.toString())
LogEx.logDebug(TAG, "getMediaVideo uri=$uri")
val path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA))
val mimeType = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.MIME_TYPE))
list.add(MediaBean(path = path, uri = uri, mimeType = mimeType))
}
}
} catch (e: Exception) {
} finally {
cursor?.close()
}
return list
}
fun Context.getMediaAudio(): List<MediaBean> {
val list = arrayListOf<MediaBean>()
val contentResolver = this.contentResolver
// 定义查询的Uri和列
val baseUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
val projection = arrayOf(MediaStore.Audio.Media._ID, MediaStore.Audio.Media.DATA, MediaStore.Audio.Media.MIME_TYPE)
// 执行查询
var cursor: Cursor? = null
try {
cursor = contentResolver.query(baseUri, projection, null, null, null)
if (cursor != null) {
while (cursor.moveToNext()) {
val id = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID))
val uri = Uri.withAppendedPath(baseUri, id.toString())
val path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA))
val mimeType = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.MIME_TYPE))
list.add(MediaBean(path = path, uri = uri, mimeType = mimeType))
}
}
} catch (e: Exception) {
} finally {
cursor?.close()
}
return list
}
@SuppressLint("Range")
fun Context.getMediaVideoCountSize(): Pair<Int, Long> {
var count = 0
var totalSize: Long = 0
runCatching {
val contentResolver = this.contentResolver
// 定义查询的Uri和列
val uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI
val projection = arrayOf(MediaStore.Video.Media._ID, MediaStore.Video.Media.SIZE)
// 执行查询
val cursor = contentResolver.query(uri, projection, null, null, null)
// 检查cursor是否包含数据
count = cursor?.count ?: 0
while (cursor?.moveToNext() == true) {
totalSize += cursor.getInt(cursor.getColumnIndex(MediaStore.Video.Media.SIZE))
}
// 关闭cursor
cursor?.close()
}
return Pair(count, totalSize)
}
@SuppressLint("Range")
fun Context.getMediaAudioCountSize(): Pair<Int, Long> {
var count = 0
var totalSize: Long = 0
runCatching {
val contentResolver = this.contentResolver
// 定义查询的Uri和列
val uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
val projection = arrayOf(
MediaStore.Audio.Media._ID,
MediaStore.Audio.Media.SIZE,
)
// 执行查询
val cursor = contentResolver.query(uri, projection, null, null, null)
// 检查cursor是否包含数据
count = cursor?.count ?: 0
while (cursor?.moveToNext() == true) {
totalSize += cursor.getInt(cursor.getColumnIndex(MediaStore.Audio.Media.SIZE))
}
// 关闭cursor
cursor?.close()
}
return Pair(count, totalSize)
}
fun Context.getMediaDocumentCountSize(): Int {
var count = 0
runCatching {
val contentResolver = this.contentResolver
val mimeTypeSelectionArgs = arrayOf(
MIME_TYPE_PDF,
MIME_TYPE_DOC,
MIME_TYPE_DOCX,
MIME_TYPE_XLS,
MIME_TYPE_XLSX,
MIME_TYPE_PPT,
MIME_TYPE_PPTX,
)
val mimeTypeSelection =
"${MediaStore.Files.FileColumns.MIME_TYPE} IN (" + mimeTypeSelectionArgs.joinToString(",") { "?" } + ")"
// 定义查询的Uri和列
val uri = MediaStore.Files.getContentUri("external")
val projection = arrayOf(MediaStore.Files.FileColumns._ID)
// 执行查询
val cursor = contentResolver.query(uri, projection, mimeTypeSelection, mimeTypeSelectionArgs, null)
// 检查cursor是否包含数据
count = cursor?.count ?: 0
// 关闭cursor
cursor?.close()
}
return count
}
fun Context.getMediaApkCountSize(): Int {
var count = 0
runCatching {
val contentResolver = this.contentResolver
val mimeTypeSelectionArgs = arrayOf(
MIME_TYPE_APK
)
val mimeTypeSelection = "${MediaStore.Files.FileColumns.MIME_TYPE} = ?"
// 定义查询的Uri和列
val uri = MediaStore.Files.getContentUri("external")
val projection = arrayOf(MediaStore.Files.FileColumns._ID)
// 执行查询
val cursor = contentResolver.query(uri, projection, mimeTypeSelection, mimeTypeSelectionArgs, null)
// 检查cursor是否包含数据
count = cursor?.count ?: 0
// 关闭cursor
cursor?.close()
}
return count
}
fun Context.getMediaZipCountSize(): Int {
var count = 0
runCatching {
val contentResolver = this.contentResolver
val mimeTypeSelectionArgs = arrayOf(
MIME_TYPE_ZIP
)
val mimeTypeSelection = "${MediaStore.Files.FileColumns.MIME_TYPE} = ?"
// 定义查询的Uri和列
val uri = MediaStore.Files.getContentUri("external")
val projection = arrayOf(MediaStore.Files.FileColumns._ID)
// 执行查询
val cursor = contentResolver.query(uri, projection, mimeTypeSelection, mimeTypeSelectionArgs, null)
// 检查cursor是否包含数据
count = cursor?.count ?: 0
// 关闭cursor
cursor?.close()
}
return count
}
private fun getFileTypeSelection(fileSuffix: String): String {
return (MediaStore.Files.FileColumns.MEDIA_TYPE + "="
+ MediaStore.Files.FileColumns.MEDIA_TYPE_NONE + " AND "
+ MediaStore.Files.FileColumns.DATA + " LIKE '%" + fileSuffix + "'")
}
fun CoroutineScope.queryFiles(context: Context, fileSuffix: String, flow: MutableSharedFlow<String>? = null) =
async(Dispatchers.IO) {
val selection = getFileTypeSelection(fileSuffix)
val fileList: MutableList<File> = ArrayList()
val projection = arrayOf(
MediaStore.Files.FileColumns._ID, MediaStore.Files.FileColumns.DATA,
)
val sortOrder = MediaStore.Files.FileColumns._ID + " DESC"
val queryUri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL)
} else {
MediaStore.Files.getContentUri("external")
}
val cursor = context.contentResolver.query(queryUri, projection, selection, null, sortOrder)
if (cursor != null) {
while (cursor.moveToNext()) {
delay(150)
val path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DATA))
flow?.emit(path)
fileList.add(File(path))
}
cursor.close()
}
fileList
}
fun queryFiles(context: Context, fileSuffix: String): MutableList<File> {
val selection = getFileTypeSelection(fileSuffix)
val fileList: MutableList<File> = ArrayList()
val projection = arrayOf(
MediaStore.Files.FileColumns._ID, MediaStore.Files.FileColumns.DATA,
)
val sortOrder = MediaStore.Files.FileColumns._ID + " DESC"
val queryUri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL)
} else {
MediaStore.Files.getContentUri("external")
}
val cursor = context.contentResolver.query(queryUri, projection, selection, null, sortOrder)
if (cursor != null) {
while (cursor.moveToNext()) {
val path = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.DATA))
fileList.add(File(path))
}
cursor.close()
}
return fileList
}
fun getFileNameFromUri(context: Context, uri: Uri): String {
var displayName = ""
if (DocumentsContract.isDocumentUri(context, uri)) {
val projection = arrayOf(OpenableColumns.DISPLAY_NAME)
var cursor: Cursor? = null
try {
cursor = context.contentResolver.query(uri, projection, null, null, null)
val column_index = cursor!!.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME)
if (cursor.moveToFirst()) {
displayName = cursor.getString(column_index)
}
} catch (e: java.lang.Exception) {
e.printStackTrace()
} finally {
cursor?.close()
}
}
return displayName
}
\ No newline at end of file
package com.base.pdfreaderallpdfreader.utils
import android.content.Context
import android.graphics.Bitmap
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import android.net.Uri
import com.base.pdfreaderallpdfreader.utils.UriUtils.readFileToByteArray
import com.tom_roush.pdfbox.pdmodel.PDDocument
import com.tom_roush.pdfbox.pdmodel.PDPage
import com.tom_roush.pdfbox.pdmodel.PDPageContentStream
import com.tom_roush.pdfbox.pdmodel.common.PDRectangle
import com.tom_roush.pdfbox.pdmodel.encryption.AccessPermission
import com.tom_roush.pdfbox.pdmodel.encryption.StandardProtectionPolicy
import com.tom_roush.pdfbox.pdmodel.graphics.image.PDImageXObject
import com.tom_roush.pdfbox.rendering.ImageType
import com.tom_roush.pdfbox.rendering.PDFRenderer
import com.tom_roush.pdfbox.rendering.RenderDestination
import java.io.File
import java.io.IOException
object PdfBoxUtils {
private val TAG = "PdfUtils"
fun Context.getNumberOfPages(filePath: String, password: String? = null, uri: String? = null): Int {
val document =
loadPDDocument(path = filePath, password, uri)
return document.numberOfPages
}
fun Context.getPdfDrawablePage(
context: Context,
filePath: String,
password: String? = null,
uri: String? = null,
pageIndex: Int,
scale: Float = 1f,
): Drawable {
val document = loadPDDocument(filePath, password, uri)
val renderer = PDFRenderer(document)
val bitmap: Bitmap = renderer.renderImage(pageIndex, scale, ImageType.RGB, RenderDestination.EXPORT)
val drawable = BitmapDrawable(context.resources, bitmap)
return drawable
}
fun Context.checkPdfEncryption(filePath: String = "", uri: String? = null): Int {
var state = 0
var pdfDocument: PDDocument? = null
try {
pdfDocument = loadPDDocument(filePath, null, uri)
pdfDocument.use { document ->
if (document.isEncrypted) {
println("The PDF is encrypted.")
val ap = document.getCurrentAccessPermission()
if (ap.canExtractContent()) {
println("You are allowed to extract content.")
} else {
state = 1
println("You are not allowed to extract content.")
}
if (ap.canPrint()) {
println("You are allowed to print the document.")
} else {
println("You are not allowed to print the document.")
state = 1
}
} else {
println("The PDF is not encrypted.")
state = 0
}
}
} catch (e: IOException) {
e.printStackTrace()
state = 1
} finally {
pdfDocument?.close()
}
return state
}
fun setPassword(
sourceFilePath: String,
userPassword: String,
ownerPassword: String
): Boolean {
try {
PDDocument.load(File(sourceFilePath)).use { document ->
val ap = AccessPermission()
ap.setCanPrint(false)
ap.setCanModify(false)
ap.setCanExtractContent(false)
ap.setCanExtractForAccessibility(false)
ap.setCanFillInForm(false)
val spp = StandardProtectionPolicy(userPassword, ownerPassword, ap)
document.protect(spp)
document.save(File(sourceFilePath))
LogEx.logDebug(TAG, "setPassword finish")
}
} catch (e: Exception) {
LogEx.logDebug(TAG, "setPassword Exception ${e.printStackTrace()}")
e.printStackTrace()
return false
}
return true
}
fun clearPassword(filePath: String, password: String) {
try {
PDDocument.load(File(filePath), password).use { document ->
if (document.isEncrypted) {
val ap: AccessPermission = document.getCurrentAccessPermission()
if (ap.isOwnerPermission) {
// 创建一个新的保护策略,不设置密码
val spp = StandardProtectionPolicy(
"", "",
AccessPermission.getOwnerAccessPermission()
)
document.protect(spp)
}
}
// 保存PDF文件到新的位置,没有密码保护
document.save(File(filePath))
}
} catch (e: IOException) {
e.printStackTrace()
}
}
fun Context.checkPwd(
filePath: String,
password: String,
uri: String? = null
): Boolean {
try {
val pdfDocument = loadPDDocument(filePath, password, uri)
// 尝试使用提供的密码加载PDF文件
pdfDocument.use { document ->
// 如果没有抛出异常,说明密码正确
return true
}
} catch (e: Exception) {
// 加载文件时,如果密码保护策略异常,密码可能错误
println("Incorrect password or restricted permissions.")
} catch (e: IOException) {
// 其他I/O异常处理
println("An I/O error occurred: " + e.message)
}
return false
}
private fun Context.loadPDDocument(path: String, password: String?, uri: String? = null): PDDocument {
return if (uri == null) {
if (password == null) {
PDDocument.load(File(path))
} else {
PDDocument.load(File(path), password)
}
} else {
if (password == null) {
PDDocument.load(readFileToByteArray(this, Uri.parse(uri)) ?: byteArrayOf())
} else {
PDDocument.load(readFileToByteArray(this, Uri.parse(uri)) ?: byteArrayOf(), password)
}
}
}
fun saveNewPdf(imagePath: String, savePath: String) {
try {
PDDocument().use { document ->
// 添加一个页面
val page = PDPage(PDRectangle.A4)
document.addPage(page)
// 加载图片
val image = PDImageXObject.createFromFile(imagePath, document)
// 计算图片在页面中的位置和尺寸
val x = (PDRectangle.A4.width - image.width) / 2
val y = (PDRectangle.A4.height - image.height) / 2
PDPageContentStream(document, page).use { contentStream ->
contentStream.drawImage(
image,
x,
y,
image.width.toFloat(),
image.height.toFloat()
)
}
// 保存PDF文档
document.save(savePath)
}
} catch (e: IOException) {
e.printStackTrace()
}
}
}
\ No newline at end of file
package com.base.pdfreaderallpdfreader.utils
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.ActivityCompat
object PermissionUtils {
fun Context.checkStorePermission(): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
Environment.isExternalStorageManager()
} else {
val readPermission = ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
val writePermission = ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
return readPermission == PackageManager.PERMISSION_GRANTED && writePermission == PackageManager.PERMISSION_GRANTED;
}
}
fun Context.checkNotificationPermission(): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
ActivityCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED
} else {
return true
}
}
fun Context.requestStoragePermission(
launcher: ActivityLauncher,
jumpAction: (() -> Unit)? = null,
result: (flag: Boolean) -> Unit
) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
val intent =
Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION)
intent.addCategory("android.intent.category.DEFAULT")
intent.data = Uri.parse("package:${packageName}")
jumpAction?.invoke()
launcher.launch(intent) {
result.invoke(checkStorePermission())
}
} else {
launcher.launch(arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { map ->
result(map.values.all { it })
}
}
}
}
\ No newline at end of file
package com.base.pdfreaderallpdfreader.utils
object SpStringUtils {
private val TAG = "SpStringUtils"
const val BOOKMARK_KEY = "bookmark_key"
//key=last_view_key value=/data/user/0/com.ttesst.gododo.redause/files/demo/DEMO.pdf_/_1728703007625
const val LAST_VIEW_KEY = "last_view_key"
fun getSpStringList(key: String): List<String> {
val sp = AppPreferences.getInstance().getString(key, "")
return if (sp.equals("")) {
listOf()
} else {
sp.split("|||")
}
}
fun addSpString(key: String, value: String) {
LogEx.logDebug(TAG, "key=$key value=$value")
val list = getSpStringList(key).toMutableList()
list.add(value)
val string = list.joinToString(separator = "|||")
AppPreferences.getInstance().put(key, string)
}
fun deleteSpString(key: String, value: String) {
val list = getSpStringList(key).toMutableList()
list.remove(value)
val string = list.joinToString(separator = "|||")
AppPreferences.getInstance().put(key, string)
}
}
\ No newline at end of file
package com.base.pdfreaderallpdfreader.utils
import android.content.Context
import android.net.Uri
import com.tom_roush.pdfbox.io.IOUtils
import java.io.InputStream
object UriUtils {
fun readFileToByteArray(context: Context, uri: Uri): ByteArray? {
var inputStream: InputStream? = null
return try {
inputStream = context.contentResolver.openInputStream(uri)
// 读取文件内容到字节数组
IOUtils.toByteArray(inputStream)
} catch (e: java.lang.Exception) {
e.printStackTrace()
null
} finally {
if (inputStream != null) {
try {
inputStream.close()
} catch (e: java.lang.Exception) {
e.printStackTrace()
}
}
}
}
}
\ No newline at end of file
package com.base.pdfreaderallpdfreader.utils
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
object XmlEx {
fun Int.inflate(parent: ViewGroup, attachToRoot: Boolean = false): View {
return LayoutInflater.from(parent.context).inflate(this, parent, attachToRoot)
}
fun Int.inflate(context: Context, attachToRoot: Boolean = false): View {
return LayoutInflater.from(context).inflate(this, null, attachToRoot)
}
}
\ No newline at end of file
package com.base.pdfreaderallpdfreader.widget
import android.app.Service
import android.content.Context
import android.util.AttributeSet
import android.util.DisplayMetrics
import android.view.WindowManager
import androidx.drawerlayout.widget.DrawerLayout
import com.google.android.material.navigation.NavigationView
class FullScreenNavigationView : NavigationView {
constructor(context: Context) : super(context) {
initView(context)
}
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
initView(context)
}
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
initView(context)
}
private fun initView(context: Context) {
val vto = this.viewTreeObserver
vto.addOnGlobalLayoutListener { setFullScreenWidth(context) }
}
fun setFullScreenWidth(context: Context) {
val displayMetrics = DisplayMetrics()
val windowManager = context.getSystemService(Service.WINDOW_SERVICE) as WindowManager
windowManager.getDefaultDisplay().getMetrics(displayMetrics)
val screenWidth = displayMetrics.widthPixels
val params = this.layoutParams as DrawerLayout.LayoutParams
params.width = screenWidth
this.layoutParams = params
}
}
\ No newline at end of file
package com.base.pdfreaderallpdfreader.widget
import android.content.Context
import android.graphics.Canvas
import android.util.AttributeSet
import com.airbnb.lottie.LottieAnimationView
class XmlLottieAnimationView : LottieAnimationView {
constructor(context: Context?) : super(context)
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
override fun draw(canvas: Canvas) {
try {
super.draw(canvas)
} catch (e: Exception) {
}
}
override fun playAnimation() {
super.playAnimation()
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#58585A" android:state_selected="false" />
<item android:color="#4385F5" android:state_selected="true" />
</selector>
\ 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="22dp" />
<solid android:color="#6EAAFF" />
</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="#EAFFF3" />
<corners android:radius="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="#EDF3FF" />
<corners android:radius="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="#EFEFEF" />
<corners android:radius="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="#F6F6F6" />
<corners android:radius="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="#FFF1EC" />
<corners android:radius="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"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@mipmap/pdf_unchecked" android:state_selected="false" />
<item android:drawable="@mipmap/pdf_selected" android:state_selected="true" />
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@mipmap/pdf_tab_select" android:state_selected="true" />
<item android:drawable="@mipmap/pdf_tab_unselect" android:state_selected="false" />
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>
\ No newline at end of file
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M12,12m-3.2,0a3.2,3.2 0,1 1,6.4 0a3.2,3.2 0,1 1,-6.4 0" />
<path
android:fillColor="#FF000000"
android:pathData="M9,2L7.17,4H4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2V6c0,-1.1 -0.9,-2 -2,-2h-3.17L15,2H9zm3,15c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5z" />
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M22,16V4c0,-1.1 -0.9,-2 -2,-2H8c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2zm-11,-4l2.03,2.71L16,11l4,5H8l3,-4zM2,6v14c0,1.1 0.9,2 2,2h14v-2H4V6H2z" />
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M4,6H2v14c0,1.1 0.9,2 2,2h14v-2H4V6zm16,-4H8c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2V4c0,-1.1 -0.9,-2 -2,-2zm-8,12.5v-9l6,4.5 -6,4.5z" />
</vector>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="2dp" />
<solid android:color="@color/white" />
<!-- <gradient-->
<!-- android:endColor="#FAF8D1"-->
<!-- android:startColor="#FAD4E7"-->
<!-- android:type="linear" />-->
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#20000000">
</ripple>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@mipmap/h_tab_bookmark_n" android:state_selected="false" />
<item android:drawable="@mipmap/h_tab_bookmark_s" android:state_selected="true" />
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@mipmap/h_tab_home_n" android:state_selected="false" />
<item android:drawable="@mipmap/h_tab_home_s" android:state_selected="true" />
</selector>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@mipmap/h_tab_recent_n" android:state_selected="false" />
<item android:drawable="@mipmap/h_tab_recent_s" android:state_selected="true" />
</selector>
\ No newline at end of file
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:angle="135"
android:centerColor="#009688"
android:endColor="#00695C"
android:startColor="#4DB6AC"
android:type="linear" />
</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"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
tools:context=".ui.document.DocumentActivity">
<FrameLayout
android:id="@+id/fl_fanhui"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10sp"
android:layout_marginTop="24dp"
android:padding="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/pdf_arrow"
tools:ignore="ContentDescription" />
</FrameLayout>
<TextView
android:id="@+id/tv_tittle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:textColor="@color/black"
android:textSize="23sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@id/fl_fanhui"
app:layout_constraintStart_toEndOf="@id/fl_fanhui"
app:layout_constraintTop_toTopOf="@id/fl_fanhui"
tools:text="PDF Reader" />
<ImageView
android:id="@+id/iv_search"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="18dp"
android:src="@mipmap/h_sousuo"
app:layout_constraintBottom_toBottomOf="@id/fl_fanhui"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/fl_fanhui"
tools:ignore="ContentDescription" />
<FrameLayout
android:id="@+id/fl_tab"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:background="@color/white"
app:layout_constraintTop_toBottomOf="@id/fl_fanhui">
<com.angcyo.tablayout.DslTabLayout
android:id="@+id/tabLayout_document"
android:layout_width="match_parent"
android:layout_height="50dp"
app:tab_badge_gravity="center"
app:tab_badge_offset_x="20dp"
app:tab_draw_indicator="true"
app:tab_enable_text_color="true"
app:tab_indicator_anim="true"
app:tab_indicator_drawable="@drawable/indicator_bottom_line"
app:tab_indicator_height="3dp"
app:tab_indicator_width="30dp"
app:tab_item_is_equ_width="true">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/ripple_select"
android:clipChildren="false"
android:clipToPadding="false"
android:gravity="center"
android:text="All"
android:textSize="16sp"
android:textStyle="bold"
tools:ignore="HardcodedText" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/ripple_select"
android:clipChildren="false"
android:clipToPadding="false"
android:gravity="center"
android:text="PDF"
android:textSize="16sp"
android:textStyle="bold"
tools:ignore="HardcodedText" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@drawable/ripple_select"
android:clipChildren="false"
android:clipToPadding="false"
android:gravity="center"
android:paddingVertical="5dp"
android:text="Word"
android:textSize="16sp"
android:textStyle="bold"
tools:ignore="HardcodedText" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/ripple_select"
android:clipChildren="false"
android:clipToPadding="false"
android:gravity="center"
android:text="Excel"
android:textSize="16sp"
android:textStyle="bold"
tools:ignore="HardcodedText" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/ripple_select"
android:clipChildren="false"
android:clipToPadding="false"
android:gravity="center"
android:text="PPT"
android:textSize="16sp"
android:textStyle="bold"
tools:ignore="HardcodedText" />
</com.angcyo.tablayout.DslTabLayout>
</FrameLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/fl_tab">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager2"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
</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:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.language.LanguageActivity">
<FrameLayout
android:id="@+id/fl_fanhui"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10sp"
android:layout_marginTop="24dp"
android:padding="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/pdf_arrow" />
</FrameLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:text="@string/select_language"
android:textColor="@color/black"
android:textSize="23sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@id/fl_fanhui"
app:layout_constraintStart_toEndOf="@id/fl_fanhui"
app:layout_constraintTop_toTopOf="@id/fl_fanhui" />
<ImageView
android:id="@+id/iv_right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="20dp"
android:src="@mipmap/pdf_icon_right"
app:layout_constraintBottom_toBottomOf="@id/fl_fanhui"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/fl_fanhui" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintTop_toBottomOf="@id/fl_fanhui"
tools:listitem="@layout/item_language_set" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout 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:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<include
android:id="@+id/include_main"
layout="@layout/layout_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.base.pdfreaderallpdfreader.widget.FullScreenNavigationView
android:id="@+id/nav_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white">
<FrameLayout
android:id="@+id/fl_fanhui"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10sp"
android:layout_marginTop="48dp"
android:padding="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/pdf_arrow"
tools:ignore="ContentDescription" />
</FrameLayout>
<TextView
android:id="@+id/tv_pdf_reader"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="23sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@id/fl_fanhui"
app:layout_constraintStart_toEndOf="@id/fl_fanhui"
app:layout_constraintTop_toTopOf="@id/fl_fanhui"
tools:text="PDF Reader" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="28dp"
android:orientation="vertical"
app:layout_constraintTop_toBottomOf="@id/fl_fanhui">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="21dp"
android:text="@string/general"
android:textColor="#B1B3B9"
android:textSize="13sp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="10dp"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="16dp"
android:src="@mipmap/pdf_file" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginHorizontal="15dp"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/file_manager"
android:textColor="@color/black"
android:textSize="15sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/access_and_manage_your_documents"
android:textColor="#929295"
android:textSize="10sp" />
</LinearLayout>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="38dp"
android:src="@mipmap/pdf_right" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="10dp"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="16dp"
android:src="@mipmap/pdf_language" />
<LinearLayout
android:id="@+id/ll_language"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginHorizontal="15dp"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/language"
android:textColor="@color/black"
android:textSize="15sp" />
<TextView
android:id="@+id/tv_language"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:textColor="#929295"
android:textSize="10sp" />
</LinearLayout>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="38dp"
android:src="@mipmap/pdf_right" />
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="21dp"
android:layout_marginTop="36dp"
android:text="Others"
android:textColor="#B1B3B9"
android:textSize="13sp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="10dp"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="16dp"
android:src="@mipmap/pdf_rate" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginHorizontal="15dp"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/rate_us"
android:textColor="@color/black"
android:textSize="15sp" />
</LinearLayout>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="38dp"
android:src="@mipmap/pdf_right" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="10dp"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="16dp"
android:src="@mipmap/pdf_share" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginHorizontal="15dp"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/share"
android:textColor="@color/black"
android:textSize="15sp" />
</LinearLayout>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="38dp"
android:src="@mipmap/pdf_right" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="10dp"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="16dp"
android:src="@mipmap/pdf_privacy" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginHorizontal="15dp"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/privacy_policy"
android:textColor="@color/black"
android:textSize="15sp" />
</LinearLayout>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="38dp"
android:src="@mipmap/pdf_right" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="10dp"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="16dp"
android:src="@mipmap/pdf_feedback" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginHorizontal="15dp"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Feedback"
android:textColor="@color/black"
android:textSize="15sp" />
</LinearLayout>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginEnd="38dp"
android:src="@mipmap/pdf_right" />
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.base.pdfreaderallpdfreader.widget.FullScreenNavigationView>
</androidx.drawerlayout.widget.DrawerLayout>
\ 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:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
tools:context=".ui.search.SearchActivity">
<FrameLayout
android:id="@+id/fl_fanhui"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_marginTop="24dp"
android:padding="15dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@mipmap/pdf_arrow"
tools:ignore="ContentDescription" />
</FrameLayout>
<EditText
android:id="@+id/edit"
android:layout_width="0dp"
android:layout_height="45dp"
android:layout_marginStart="5dp"
android:layout_marginEnd="15dp"
android:background="@drawable/bg_efefef_15"
android:hint="@string/search_documents"
android:imeOptions="actionDone"
android:paddingStart="27dp"
android:singleLine="true"
android:textSize="15sp"
app:layout_constraintBottom_toBottomOf="@id/fl_fanhui"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/fl_fanhui"
app:layout_constraintTop_toTopOf="@id/fl_fanhui"
tools:ignore="Autofill,RtlSymmetry,TextFields,TouchTargetSizeCheck" />
<com.angcyo.tablayout.DslTabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="35dp"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="18dp"
app:layout_constraintTop_toBottomOf="@id/fl_fanhui"
app:tab_deselect_color="#8F8F8F"
app:tab_divider_solid_color="@android:color/transparent"
app:tab_divider_width="30dp"
app:tab_draw_divider="true"
app:tab_enable_ico_color="false"
app:tab_indicator_style="STYLE_NONE"
app:tab_item_default_height="30dp"
app:tab_select_color="@color/white" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginVertical="18dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/tabLayout"
tools:listitem="@layout/item_document" />
<LinearLayout
android:id="@+id/ll_empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="vertical"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tabLayout"
tools:ignore="UseCompoundDrawables">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:src="@mipmap/r_pdf_no"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="8dp"
android:text="@string/no_recent"
android:textColor="#2A2A2A"
android:textSize="15sp"
android:textStyle="bold" />
</LinearLayout>
</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:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
tools:context=".ui.splash.SplashActivity">
<ImageView
android:id="@+id/iv_logo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="220dp"
android:src="@mipmap/logox"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/tv_spanner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/iv_logo"
tools:ignore="HardcodedText"
tools:text="AII PDF Reader" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:text="@string/one_application_for_all_documents"
android:textColor="#8A8A8A"
android:textSize="12sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_spanner" />
</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="wrap_content"
android:background="@drawable/bg_ffffff_tlr15"
android:orientation="vertical">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="16dp"
android:src="@mipmap/pdf_permissions"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="24dp"
android:text="@string/permission_required"
android:textColor="#333333"
android:textSize="17sp"
android:textStyle="bold"
tools:ignore="HardcodedText" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginHorizontal="40dp"
android:layout_marginTop="16dp"
android:gravity="center"
android:textColor="#666666"
android:textSize="15sp"
tools:ignore="HardcodedText"
tools:text="To read and edit documents on your device, please allow PDF Reader to access all your files" />
<TextView
android:id="@+id/tv_allow"
android:layout_width="338dp"
android:layout_height="48dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="20dp"
android:layout_marginBottom="34dp"
android:background="@drawable/bg_6eaaff_22"
android:gravity="center"
android:text="@string/allow"
android:textColor="@color/white"
android:textSize="18sp"
tools:ignore="HardcodedText" />
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
tools:context=".ui.main.recent.RecentFragment">
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/swipeRefreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/item_document" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
<LinearLayout
android:id="@+id/ll_empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="vertical"
android:visibility="gone"
tools:ignore="UseCompoundDrawables">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:src="@mipmap/r_pdf_no"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="8dp"
android:text="@string/no_recent"
android:textColor="#2A2A2A"
android:textSize="15sp"
android:textStyle="bold" />
</LinearLayout>
</FrameLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
tools:context=".ui.document.DocumentFragment">
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/swipeRefreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginVertical="16dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/item_document" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
<LinearLayout
android:id="@+id/ll_empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="vertical"
android:visibility="gone"
tools:ignore="UseCompoundDrawables">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:src="@mipmap/r_pdf_no"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="8dp"
android:text="@string/no_document"
android:textColor="#2A2A2A"
android:textSize="15sp"
android:textStyle="bold" />
</LinearLayout>
</FrameLayout>
\ 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"
tools:context=".ui.gallery.GalleryFragment">
<TextView
android:id="@+id/text_gallery"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:textAlignment="center"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</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"
tools:context=".ui.main.home.HomeFragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_pdf_reader"
android:layout_width="match_parent"
android:layout_height="121dp"
android:layout_marginHorizontal="15dp"
android:layout_marginTop="18dp"
android:background="@mipmap/h_background"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/tv_pdf"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="24dp"
android:text="@string/pdf_reader"
android:textColor="#E20001"
android:textSize="20sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_view_edit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/view_and_edit_fles"
android:textColor="#773636"
android:textSize="13sp"
app:layout_constraintStart_toStartOf="@id/tv_pdf"
app:layout_constraintTop_toBottomOf="@id/tv_pdf" />
<TextView
android:id="@+id/tv_file_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#773636"
android:textSize="14sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="@id/tv_pdf"
app:layout_constraintTop_toBottomOf="@id/tv_view_edit"
tools:text="2 Files" />
<ImageView
android:id="@+id/iv_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:src="@mipmap/icon_r_arrow"
app:layout_constraintBottom_toBottomOf="@id/tv_file_number"
app:layout_constraintStart_toEndOf="@id/tv_file_number"
app:layout_constraintTop_toTopOf="@id/tv_file_number"
tools:ignore="ContentDescription" />
</androidx.constraintlayout.widget.ConstraintLayout>
<LinearLayout
android:id="@+id/ll_function"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="10dp"
android:layout_marginTop="10dp"
android:orientation="horizontal"
app:layout_constraintTop_toBottomOf="@id/cl_pdf_reader"
tools:ignore="DisableBaselineAlignment">
<LinearLayout
android:id="@+id/ll_edit_pdf"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="5dp"
android:layout_weight="1"
android:orientation="vertical"
tools:ignore="UseCompoundDrawables">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="@mipmap/h_edit_pdf"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="11dp"
android:text="Edit PDF"
android:textColor="#1E201E"
android:textSize="12sp"
tools:ignore="HardcodedText" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_merge_pdf"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="5dp"
android:layout_weight="1"
android:orientation="vertical"
tools:ignore="UseCompoundDrawables">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="@mipmap/h_merge_pdf"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="11dp"
android:text="Merge PDF"
android:textColor="#1E201E"
android:textSize="12sp"
tools:ignore="HardcodedText" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_split_pdf"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="5dp"
android:layout_weight="1"
android:orientation="vertical"
tools:ignore="UseCompoundDrawables">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="@mipmap/h_split_pdf"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="11dp"
android:text="Merge PDF"
android:textColor="#1E201E"
android:textSize="12sp"
tools:ignore="HardcodedText" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_lock_pdf"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="5dp"
android:layout_weight="1"
android:orientation="vertical"
tools:ignore="UseCompoundDrawables">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="@mipmap/h_lock_pdf"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="11dp"
android:text="Merge PDF"
android:textColor="#1E201E"
android:textSize="12sp"
tools:ignore="HardcodedText" />
</LinearLayout>
</LinearLayout>
<TextView
android:id="@+id/tv_documents"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginTop="30dp"
android:text="@string/other_documents"
android:textColor="#B1B3B9"
android:textSize="13sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/ll_function" />
<LinearLayout
android:id="@+id/ll_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="15dp"
android:layout_marginTop="16dp"
android:orientation="horizontal"
app:layout_constraintTop_toBottomOf="@id/tv_documents"
tools:ignore="DisableBaselineAlignment">
<LinearLayout
android:layout_width="0dp"
android:layout_height="108dp"
android:layout_marginEnd="6dp"
android:layout_weight="1"
android:background="@drawable/bg_edf3ff_15"
android:orientation="vertical">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="20dp"
android:src="@mipmap/h_word"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="8dp"
android:includeFontPadding="false"
android:text="@string/word_reader"
android:textColor="#1E201E"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="8dp"
android:textColor="#B1B3B9"
android:textSize="12sp"
tools:text="2 Files" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="108dp"
android:layout_marginStart="6dp"
android:layout_weight="1"
android:background="@drawable/bg_fff1ec_15"
android:orientation="vertical">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="20dp"
android:src="@mipmap/h_ppt"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="8dp"
android:includeFontPadding="false"
android:text="@string/ppt_reader"
android:textColor="#1E201E"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="8dp"
android:textColor="#B1B3B9"
android:textSize="12sp"
tools:text="2 Files" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="15dp"
android:layout_marginTop="16dp"
android:orientation="horizontal"
app:layout_constraintTop_toBottomOf="@id/ll_1">
<LinearLayout
android:layout_width="0dp"
android:layout_height="108dp"
android:layout_marginEnd="6dp"
android:layout_weight="1"
android:background="@drawable/bg_eafff3_15"
android:orientation="vertical">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="20dp"
android:src="@mipmap/h_excel"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="8dp"
android:includeFontPadding="false"
android:text="@string/excel_reader"
android:textColor="#1E201E"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="8dp"
android:textColor="#B1B3B9"
android:textSize="12sp"
tools:text="2 Files" />
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="108dp"
android:layout_marginStart="6dp"
android:layout_weight="1"
android:background="@drawable/bg_f6f6f6_15"
android:orientation="vertical">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="20dp"
android:src="@mipmap/h_word"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="8dp"
android:includeFontPadding="false"
android:text="@string/other_reader"
android:textColor="#1E201E"
android:textSize="14sp"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="8dp"
android:textColor="#B1B3B9"
android:textSize="12sp"
tools:text="2 Files" />
</LinearLayout>
</LinearLayout>
</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="match_parent"
android:orientation="vertical"
tools:context=".ui.main.PermissionFragment">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="148dp"
android:src="@mipmap/pdf_permissions"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="18dp"
android:text="@string/permission_required"
android:textColor="@color/black"
android:textSize="18sp"
android:textStyle="bold" />
<TextView
android:id="@+id/tv_spanner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="40dp"
android:layout_marginTop="20dp"
android:gravity="center"
android:textColor="#D3D6DE"
android:textSize="15sp"
tools:text="To read and edit documents on your device, please allow PDF Reader to access all your files" />
<TextView
android:id="@+id/tv_allow"
android:layout_width="match_parent"
android:layout_height="44dp"
android:layout_marginHorizontal="18dp"
android:layout_marginTop="30dp"
android:background="@drawable/bg_6eaaff_22"
android:gravity="center"
android:text="@string/allow"
android:textColor="@color/white"
android:textSize="15sp"
android:textStyle="bold" />
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
tools:context=".ui.main.recent.RecentFragment">
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/swipeRefreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:id="@+id/rv"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/item_document" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
<LinearLayout
android:id="@+id/ll_empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="vertical"
android:visibility="gone"
tools:ignore="UseCompoundDrawables">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:src="@mipmap/r_pdf_no"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="8dp"
android:text="@string/no_recent"
android:textColor="#2A2A2A"
android:textSize="15sp"
android:textStyle="bold" />
</LinearLayout>
</FrameLayout>
\ 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"
tools:context=".ui.slideshow.SlideshowFragment">
<TextView
android:id="@+id/text_slideshow"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:textAlignment="center"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</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"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<fragment
android:id="@+id/nav_host_fragment_content_main"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toTopOf="@id/ll_bottom"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/mobile_navigation"
tools:ignore="FragmentTagUsage" />
<LinearLayout
android:id="@+id/ll_bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
tools:ignore="DisableBaselineAlignment">
<LinearLayout
android:id="@+id/ll_home"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:paddingVertical="6dp"
tools:ignore="UseCompoundDrawables">
<ImageView
android:id="@+id/iv_home"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="@drawable/selector_home"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/tv_home"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="5dp"
android:text="@string/home"
android:textColor="@color/color_selector_nav"
android:textSize="11sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_recent"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:paddingVertical="6dp"
tools:ignore="UseCompoundDrawables">
<ImageView
android:id="@+id/iv_recent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="@drawable/selector_recent"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/tv_recent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="5dp"
android:text="@string/recent"
android:textColor="@color/color_selector_nav"
android:textSize="11sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_bookmark"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical"
android:paddingVertical="6dp"
tools:ignore="UseCompoundDrawables">
<ImageView
android:id="@+id/iv_bookmark"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="@drawable/selector_bookmark"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/tv_bookmark"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="5dp"
android:text="@string/bookmark"
android:textColor="@color/color_selector_nav"
android:textSize="11sp" />
</LinearLayout>
</LinearLayout>
<ImageView
android:id="@+id/iv_scan"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="18dp"
android:layout_marginBottom="50dp"
android:src="@mipmap/h_pdf_saoyisao"
app:layout_constraintBottom_toTopOf="@id/ll_bottom"
app:layout_constraintEnd_toEndOf="parent"
tools:ignore="ContentDescription" />
</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="77dp">
<ImageView
android:id="@+id/iv_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="18dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription"
tools:src="@mipmap/r_pdf" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="11dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/fl_more"
app:layout_constraintStart_toEndOf="@id/iv_icon"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/tv_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:singleLine="true"
android:textColor="#222222"
android:textSize="15sp"
tools:text="Demo.pptx" />
<TextView
android:id="@+id/tv_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:textColor="#59595A"
android:textSize="12sp"
tools:text="01-11-2024 213B" />
</LinearLayout>
<FrameLayout
android:id="@+id/fl_more"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:padding="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/iv_pdf_more"
tools:ignore="ContentDescription" />
</FrameLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginHorizontal="14dp"
android:background="#E9E9E9"
app:layout_constraintBottom_toBottomOf="parent" />
</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="60dp"
android:background="?android:attr/selectableItemBackground">
<TextView
android:id="@+id/tv_language"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="18dp"
android:textColor="@color/black"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="English" />
<ImageView
android:id="@+id/iv_selector"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginEnd="20dp"
android:src="@drawable/bg_selector_language"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/tv"
android:layout_width="68dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:background="@drawable/bg_tab_selector"
android:gravity="center"
android:includeFontPadding="false"
android:paddingHorizontal="10dp"
android:paddingVertical="5dp"
android:textSize="15sp"
tools:text="Latest" />
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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"
tools:context=".ui.main.MainActivity">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:theme="@style/Theme.PdfReaderAllPdfReader.AppBarOverlay">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/iv_menu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginVertical="24dp"
android:layout_marginStart="16dp"
android:layout_marginTop="24dp"
android:importantForAccessibility="no"
android:src="@mipmap/h_pdf_menu"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_tittle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:textColor="@color/black"
android:textSize="23sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@id/iv_menu"
app:layout_constraintStart_toEndOf="@id/iv_menu"
app:layout_constraintTop_toTopOf="@+id/iv_menu"
tools:text="PDF Reader" />
<ImageView
android:id="@+id/iv_search"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="18dp"
android:src="@mipmap/h_sousuo"
app:layout_constraintBottom_toBottomOf="@id/iv_menu"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/iv_menu"
tools:ignore="ContentDescription" />
<View
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:background="#E6E6E6"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.appbar.AppBarLayout>
<include
android:id="@+id/include_content_main"
layout="@layout/include_content_main" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<navigation 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:id="@+id/mobile_navigation"
app:startDestination="@+id/nav_homeFragment">
<fragment
android:id="@+id/nav_homeFragment"
android:name="com.base.pdfreaderallpdfreader.ui.main.home.HomeFragment"
tools:layout="@layout/fragment_home" />
<fragment
android:id="@+id/nav_recentFragment"
android:name="com.base.pdfreaderallpdfreader.ui.main.recent.RecentFragment"
tools:layout="@layout/fragment_recent" />
<fragment
android:id="@+id/nav_bookmarkFragment"
android:name="com.base.pdfreaderallpdfreader.ui.main.bookmark.BookmarkFragment"
tools:layout="@layout/fragment_bookmark" />
</navigation>
\ No newline at end of file
<resources>
<dimen name="fab_margin">48dp</dimen>
</resources>
\ No newline at end of file
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Base.Theme.PdfReaderAllPdfReader" parent="Theme.Material3.DayNight.NoActionBar">
<!-- Customize your dark theme here. -->
<!-- <item name="colorPrimary">@color/my_dark_primary</item> -->
</style>
</resources>
\ No newline at end of file
<resources>
<dimen name="fab_margin">200dp</dimen>
</resources>
\ No newline at end of file
<resources>
<dimen name="fab_margin">48dp</dimen>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
</resources>
\ No newline at end of file
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="nav_header_vertical_spacing">8dp</dimen>
<dimen name="nav_header_height">176dp</dimen>
<dimen name="fab_margin">16dp</dimen>
</resources>
\ No newline at end of file
<resources>
<string name="app_name">Pdf Reader All Pdf Reader</string>
<string name="one_application_for_all_documents">One application for all documents</string>
<string name="menu_home">Home</string>
<string name="menu_gallery">Gallery</string>
<string name="menu_slideshow">Slideshow</string>
<string name="pdf_reader">PDF Reader</string>
<string name="view_and_edit_fles">View and edit fles</string>
<string name="other_documents">Other Documents</string>
<string name="word_reader">Word Reader</string>
<string name="ppt_reader">PPT Reader</string>
<string name="excel_reader">Excel Reader</string>
<string name="other_reader">Other Reader</string>
<string name="home">Home</string>
<string name="recent">Recent</string>
<string name="bookmark">Bookmark</string>
<string name="general">General</string>
<string name="file_manager">File Manager</string>
<string name="access_and_manage_your_documents">Access and manage your documents</string>
<string name="language">Language</string>
<string name="english">English</string>
<string name="rate_us">Rate US</string>
<string name="share">Share</string>
<string name="privacy_policy">Privacy Policy</string>
<!-- TODO: Remove or change this placeholder text -->
<string name="hello_blank_fragment">Hello blank fragment</string>
<string name="follow_system">Follow System</string>
<string name="select_language">Select Language</string>
<string name="no_recent">No recent</string>
<string name="permission_required">Permission Required</string>
<string name="allow">Allow</string>
<string name="search_documents">Search Documents...</string>
<string name="no_document">No Document</string>
</resources>
\ No newline at end of file
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Base.Theme.PdfReaderAllPdfReader" parent="Theme.Material3.DayNight.NoActionBar">
<!-- Customize your light theme here. -->
<!-- <item name="colorPrimary">@color/my_light_primary</item> -->
</style>
<style name="Theme.PdfReaderAllPdfReader" parent="Base.Theme.PdfReaderAllPdfReader" />
<style name="Theme.PdfReaderAllPdfReader.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
<style name="Theme.PdfReaderAllPdfReader.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar">
</style>
<style name="Theme.PdfReaderAllPdfReader.PopupOverlay" parent="ThemeOverlay.AppCompat.Light">
</style>
<style name="BottomSheetDialog" parent="Theme.Design.Light.BottomSheetDialog">
<item name="bottomSheetStyle">@style/bottomSheetStyleWrapper</item>
</style>
<style name="bottomSheetStyleWrapper" parent="Widget.Design.BottomSheet.Modal">
<item name="android:background">@android:color/transparent</item>
</style>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?><!--
Sample backup rules file; uncomment and customize as necessary.
See https://developer.android.com/guide/topics/data/autobackup
for details.
Note: This file is ignored for devices older that API 31
See https://developer.android.com/about/versions/12/backup-restore
-->
<full-backup-content>
<!--
<include domain="sharedpref" path="."/>
<exclude domain="sharedpref" path="device.xml"/>
-->
</full-backup-content>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?><!--
Sample data extraction rules file; uncomment and customize as necessary.
See https://developer.android.com/about/versions/12/backup-restore#xml-changes
for details.
-->
<data-extraction-rules>
<cloud-backup>
<!-- TODO: Use <include> and <exclude> to control what is backed up.
<include .../>
<exclude .../>
-->
</cloud-backup>
<!--
<device-transfer>
<include .../>
<exclude .../>
</device-transfer>
-->
</data-extraction-rules>
\ No newline at end of file
package com.base.pdfreaderallpdfreader
import org.junit.Test
import org.junit.Assert.*
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}
\ No newline at end of file
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
alias(libs.plugins.android.application) apply false
alias(libs.plugins.kotlin.android) apply false
id("com.google.gms.google-services") version "4.4.1" apply false
id("com.google.firebase.crashlytics") version "3.0.2" apply false
}
\ No newline at end of file
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. For more details, visit
# https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects
# org.gradle.parallel=true
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app's APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
# Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official
# Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true
\ No newline at end of file
[versions]
agp = "8.6.0"
kotlin = "1.9.0"
coreKtx = "1.10.1"
junit = "4.13.2"
junitVersion = "1.1.5"
espressoCore = "3.5.1"
appcompat = "1.6.1"
material = "1.10.0"
activity = "1.8.0"
constraintlayout = "2.1.4"
lifecycleLivedataKtx = "2.6.1"
lifecycleViewmodelKtx = "2.6.1"
navigationFragmentKtx = "2.6.0"
navigationUiKtx = "2.6.0"
[libraries]
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
androidx-activity = { group = "androidx.activity", name = "activity", version.ref = "activity" }
androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
androidx-lifecycle-livedata-ktx = { group = "androidx.lifecycle", name = "lifecycle-livedata-ktx", version.ref = "lifecycleLivedataKtx" }
androidx-lifecycle-viewmodel-ktx = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-ktx", version.ref = "lifecycleViewmodelKtx" }
androidx-navigation-fragment-ktx = { group = "androidx.navigation", name = "navigation-fragment-ktx", version.ref = "navigationFragmentKtx" }
androidx-navigation-ui-ktx = { group = "androidx.navigation", name = "navigation-ui-ktx", version.ref = "navigationUiKtx" }
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
#Wed Nov 06 10:32:19 CST 2024
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
pluginManagement {
repositories {
google {
content {
includeGroupByRegex("com\\.android.*")
includeGroupByRegex("com\\.google.*")
includeGroupByRegex("androidx.*")
}
}
mavenCentral()
gradlePluginPortal()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven("https://s01.oss.sonatype.org/content/groups/public")
maven("https://jitpack.io")
maven("https://android-sdk.is.com")
maven("https://dl-maven-android.mintegral.com/repository/mbridge_android_sdk_oversea")
maven("https://artifact.bytedance.com/repository/pangle")
maven("https://dl-maven-android.mintegral.com/repository/se_sdk_for_android/")
}
}
rootProject.name = "Pdf Reader All Pdf Reader"
include(":app")
\ No newline at end of file
File added
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