Commit d9ea9d36 authored by wanglei's avatar wanglei

初始化

parent b5861477
Pipeline #1313 failed with stages
*.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)
}
android {
namespace = "com.base.pdfoneread"
compileSdk = 34
defaultConfig {
applicationId = "com.base.pdfoneread"
minSdk = 24
targetSdk = 34
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
buildFeatures {
viewBinding = true
buildConfig = true
}
}
dependencies {
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.appcompat)
implementation(libs.material)
implementation(libs.androidx.activity)
implementation(libs.androidx.constraintlayout)
implementation(libs.androidx.swiperefreshlayout)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
implementation("androidx.core:core-splashscreen:1.0.0-beta02")
val nav_version = "2.8.0"
// Views/Fragments Integration
implementation("androidx.navigation:navigation-fragment:$nav_version")
implementation("androidx.navigation:navigation-ui:$nav_version")
//第三方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")
}
\ 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
<?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.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<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" />
<application
android:name=".ui.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.PdfOneRead"
tools:targetApi="31">
<activity
android:name=".ui.document.DocumentActivity"
android:exported="false" />
<activity
android:name=".ui.splash.SystemStartActivity"
android:exported="true"
android:launchMode="singleTask"
android:screenOrientation="portrait"
android:theme="@style/Theme.App.Starting"
tools:ignore="DiscouragedApi,LockedOrientationActivity">
<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="true"
android:launchMode="singleTop"
android:screenOrientation="portrait"
tools:ignore="DiscouragedApi,LockedOrientationActivity" />
</application>
</manifest>
\ No newline at end of file
package com.base.pdfoneread.bean
import com.base.pdfoneread.utils.AppPreferences
object ConstObject {
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"
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)
}
}
\ No newline at end of file
package com.base.pdfoneread.bean
import android.net.Uri
data class DocumentBean(
var path: String = "",
var uri: Uri? = null,
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_ALL = "type_all"
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.pdfoneread.bean
/**
* 全局数据数据
*/
object GlobalDocumentData {
val GlobalPdfList = arrayListOf<DocumentBean>()
val GlobalWordList = arrayListOf<DocumentBean>()
var GlobalExcelList = arrayListOf<DocumentBean>()
var GlobalPptList = arrayListOf<DocumentBean>()
}
\ No newline at end of file
package com.base.pdfoneread.bean
import com.base.pdfoneread.R
data class HomeUIBean(
val key: String = KEY_ALL,
val icon: Int = R.mipmap.h_pdf_all,
val des: String = "All",
var uiType: Int = UI_TYPE_GRID,
var fileNumber: Int = -1,
) {
var isTittle: Boolean = false
var tittle: String = ""
companion object {
const val UI_TYPE_GRID = 0
const val UI_TYPE_LIST = 1
const val UI_TYPE_TITTLE = 2
const val KEY_ALL = "key_all"
const val KEY_PDF = "key_pdf"
const val KEY_WORD = "key_word"
const val KEY_EXCEL = "key_excel"
const val KEY_PPT = "key_ppt"
const val KEY_IMAGE_TO_PDF = "key_image_to_pdf"
const val KEY_MERGE_PDF = "key_merge_pdf"
const val KEY_SPLIT_PDF = "key_split_pdf"
const val KEY_LOCK_PDF = "key_lock_pdf"
const val KEY_UNLOCK_PDF = "key_unlock_pdf"
const val KEY_SCAN_PDF = "key_scan_pdf"
const val KEY_IMAGE_PDF = "key_image_pdf"
}
}
\ No newline at end of file
package com.base.pdfoneread.bean
import android.net.Uri
data class MediaBean(
val path: String = "",
val uri: Uri = Uri.EMPTY,
val mimeType: String = ""
)
package com.base.pdfoneread.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 = "e7t5eq1u3m8nwo59"
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.pdfoneread.helper
object ConfigHelper {
const val privacyPolicy: String = "https://sites.google.com/view/editor-pdf/editor"
// const val termService: String = "https://sites.google.com/view/term-of-service-s/term-of-service"
// 正式包名
const val packageName = "com.leizi.pdftransformer"
// 域名
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",
// MyStartActivity::class.java.simpleName,
"GmsDocumentScanningDelegateActivity",
// 返回前台时不跳转启动页的 activity
)
}
\ No newline at end of file
package com.base.pdfoneread.helper
import android.os.Build
import com.base.pdfoneread.bean.ConstObject.ifAgreePrivacy
import com.base.pdfoneread.helper.ReportUtils.doPost
import com.base.pdfoneread.utils.AppPreferences
import com.base.pdfoneread.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.pdfoneread.helper;
import android.text.TextUtils;
import com.base.pdfoneread.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.pdfoneread.ui
import android.app.Dialog
import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.viewbinding.ViewBinding
import com.base.pdfoneread.helper.EventHelper
import com.base.pdfoneread.ui.main.MainActivity
import com.base.pdfoneread.utils.ActivityLauncher
import com.base.pdfoneread.utils.ActivityManagerUtils
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()
}
}
\ No newline at end of file
package com.base.pdfoneread.ui
import android.app.Application
class MyApplication : Application() {
companion object {
lateinit var appContext: MyApplication
}
override fun onCreate() {
super.onCreate()
appContext = this
}
}
\ No newline at end of file
package com.base.pdfoneread.ui.document
import com.base.pdfoneread.databinding.ActivityDocumentBinding
import com.base.pdfoneread.ui.BaseActivity
class DocumentActivity : BaseActivity<ActivityDocumentBinding>() {
var type: String = ""
override val binding: ActivityDocumentBinding by lazy {
ActivityDocumentBinding.inflate(layoutInflater)
}
override fun initView() {
type = intent.extras?.getString("type") ?: ""
}
}
\ No newline at end of file
//package com.base.pdfoneread.ui.document
//
//import android.content.Context
//import android.media.MediaScannerConnection
//import android.net.Uri
//import android.os.Environment
//import com.base.pdfoneread.ui.MyApplication.Companion.appContext
//import com.base.pdfoneread.bean.ConstObject
//import com.base.pdfoneread.bean.ConstObject.MIME_TYPE_DOC
//import com.base.pdfoneread.bean.ConstObject.MIME_TYPE_DOCX
//import com.base.pdfoneread.bean.ConstObject.MIME_TYPE_PDF
//import com.base.pdfoneread.bean.ConstObject.MIME_TYPE_PPT
//import com.base.pdfoneread.bean.ConstObject.MIME_TYPE_PPTX
//import com.base.pdfoneread.bean.ConstObject.MIME_TYPE_XLS
//import com.base.pdfoneread.bean.ConstObject.MIME_TYPE_XLSX
//import com.base.pdfoneread.bean.DocumentBean
//import com.base.pdfoneread.bean.DocumentBean.Companion.TYPE_EXCEL
//import com.base.pdfoneread.bean.DocumentBean.Companion.TYPE_PDF
//import com.base.pdfoneread.bean.DocumentBean.Companion.TYPE_PPT
//import com.base.pdfoneread.bean.DocumentBean.Companion.TYPE_WORD
//import com.base.pdfoneread.utils.AssetUtils.readByteArrayFromAsset
//import com.base.pdfoneread.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 getDocumentAppDir(): File {
// val appDir = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS), appContext.packageName)
// if (!appDir.exists())
// appDir.exists()
// return appDir
//}
//
//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 getPdfFastSize(context: Context): Int {
// val selectionArgs = arrayOf(
// MIME_TYPE_PDF
// )
// val list = context.getMediaFile(selectionArgs = selectionArgs)
// var size = list.size
// val pdfDemo = getPdfDemo(context)
// if (File(pdfDemo.path).exists()) {
// size += 1
// }
// return size
//}
//
//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")) {
// 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_PDF
// }
//}
//
//fun saveBookmarkChange(addRemove: Boolean, path: String) {
// if (addRemove) {
// SpStringUtils.addSpString(BOOKMARK_KEY, path)
// } else {
// SpStringUtils.deleteSpString(BOOKMARK_KEY, path)
// }
//}
\ No newline at end of file
package com.base.pdfoneread.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.pdfoneread.R
import com.base.pdfoneread.databinding.ItemHomeGridBinding
import com.base.pdfoneread.databinding.ItemHomeListBinding
import com.base.pdfoneread.databinding.ItemTittleHomeBinding
import com.base.pdfoneread.bean.HomeUIBean
import com.base.pdfoneread.bean.HomeUIBean.Companion.UI_TYPE_GRID
import com.base.pdfoneread.bean.HomeUIBean.Companion.UI_TYPE_LIST
import com.base.pdfoneread.utils.XmlEx.inflate
import com.chad.library.adapter4.BaseQuickAdapter
class HomeAdapter() : BaseQuickAdapter<HomeUIBean, HomeAdapter.HomeUIBeanViewHolder>() {
inner class HomeUIBeanViewHolder(view: View) : ViewHolder(view)
@SuppressLint("SetTextI18n")
override fun onBindViewHolder(holder: HomeUIBeanViewHolder, position: Int, item: HomeUIBean?) {
item ?: return
when (item.uiType) {
UI_TYPE_GRID -> {
val binding = ItemHomeGridBinding.bind(holder.itemView)
binding.ivIcon.setImageResource(item.icon)
binding.tvDes.text = item.des
if (item.fileNumber != -1) {
binding.tvFileNumber.text = "${item.fileNumber} files"
}
}
UI_TYPE_LIST -> {
val binding = ItemHomeListBinding.bind(holder.itemView)
binding.ivIcon.setImageResource(item.icon)
binding.tvDes.text = item.des
if (item.fileNumber != -1) {
binding.tvFileNumber.text = "${item.fileNumber} files"
}
}
else -> {
val binding = ItemTittleHomeBinding.bind(holder.itemView)
binding.tvTittle.text = item.tittle
}
}
}
override fun getItemViewType(position: Int, list: List<HomeUIBean>): Int {
return list[position].uiType
}
override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): HomeUIBeanViewHolder {
val layout = when (viewType) {
UI_TYPE_GRID -> R.layout.item_home_grid
UI_TYPE_LIST -> R.layout.item_home_list
else -> R.layout.item_tittle_home
}
return HomeUIBeanViewHolder(layout.inflate(parent))
}
}
package com.base.pdfoneread.ui.main
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.GridLayoutManager
import com.base.pdfoneread.R
import com.base.pdfoneread.databinding.FragmentHomeBinding
import com.base.pdfoneread.bean.HomeUIBean
import com.base.pdfoneread.bean.HomeUIBean.Companion.KEY_ALL
import com.base.pdfoneread.bean.HomeUIBean.Companion.KEY_EXCEL
import com.base.pdfoneread.bean.HomeUIBean.Companion.KEY_IMAGE_PDF
import com.base.pdfoneread.bean.HomeUIBean.Companion.KEY_IMAGE_TO_PDF
import com.base.pdfoneread.bean.HomeUIBean.Companion.KEY_LOCK_PDF
import com.base.pdfoneread.bean.HomeUIBean.Companion.KEY_MERGE_PDF
import com.base.pdfoneread.bean.HomeUIBean.Companion.KEY_PDF
import com.base.pdfoneread.bean.HomeUIBean.Companion.KEY_PPT
import com.base.pdfoneread.bean.HomeUIBean.Companion.KEY_SCAN_PDF
import com.base.pdfoneread.bean.HomeUIBean.Companion.KEY_SPLIT_PDF
import com.base.pdfoneread.bean.HomeUIBean.Companion.KEY_UNLOCK_PDF
import com.base.pdfoneread.bean.HomeUIBean.Companion.KEY_WORD
import com.base.pdfoneread.bean.HomeUIBean.Companion.UI_TYPE_GRID
import com.base.pdfoneread.bean.HomeUIBean.Companion.UI_TYPE_LIST
import com.base.pdfoneread.bean.HomeUIBean.Companion.UI_TYPE_TITTLE
class HomeFragment() : Fragment() {
private lateinit var binding: FragmentHomeBinding
private val adapter: HomeAdapter = HomeAdapter()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentHomeBinding.inflate(layoutInflater)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val gridLayoutManager = GridLayoutManager(requireContext(), 4)
gridLayoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
override fun getSpanSize(position: Int): Int {
val item = groupList[position]
return if (item.uiType == UI_TYPE_LIST) 4 else if (item.isTittle) 4 else 1
}
}
binding.rv.layoutManager = gridLayoutManager
binding.rv.adapter = adapter
adapter.submitList(groupList)
binding.swipeRefreshLayout.setOnRefreshListener {
refreshData()
}
}
private fun refreshData() {
}
fun changeUIByMain() {
val activity = requireActivity() as MainActivity?
activity ?: return
if (activity.homeUiType == UI_TYPE_GRID) {
changeGridUI()
} else {
changeListUI()
}
}
private fun changeGridUI() {
groupList.forEach {
if (it.isTittle) {
it.uiType = UI_TYPE_TITTLE
} else {
it.uiType = UI_TYPE_GRID
}
}
adapter.submitList(groupList)
}
private fun changeListUI() {
groupList.forEach {
if (it.isTittle) {
it.uiType = UI_TYPE_TITTLE
} else {
it.uiType = UI_TYPE_LIST
}
}
adapter.submitList(groupList)
}
companion object {
val groupList = listOf(
HomeUIBean(uiType = UI_TYPE_TITTLE).apply {
isTittle = true
tittle = "Document"
},
HomeUIBean(KEY_ALL, R.mipmap.h_pdf_all, "All"),
HomeUIBean(KEY_PDF, R.mipmap.h_pdf_pdf, "PDF"),
HomeUIBean(KEY_WORD, R.mipmap.h_pdf_word, "Word"),
HomeUIBean(KEY_EXCEL, R.mipmap.h_pdf_excel, "Excel"),
HomeUIBean(KEY_PPT, R.mipmap.h_pdf_ppt, "PPT"),
HomeUIBean(uiType = UI_TYPE_TITTLE).apply {
isTittle = true
tittle = "Tools"
},
HomeUIBean(KEY_IMAGE_TO_PDF, R.mipmap.h_pdf_edit, "Image to PDF"),
HomeUIBean(KEY_MERGE_PDF, R.mipmap.h_pdf_merge, "Merge PDF"),
HomeUIBean(KEY_SPLIT_PDF, R.mipmap.h_pdf_split, "Split PDF"),
HomeUIBean(KEY_LOCK_PDF, R.mipmap.h_pdf_lock, "Lock PDF"),
HomeUIBean(KEY_UNLOCK_PDF, R.mipmap.h_pdf_unlock, "UnLock PDF"),
HomeUIBean(KEY_SCAN_PDF, R.mipmap.h_pdf_scan, "Scan PDF"),
HomeUIBean(KEY_IMAGE_PDF, R.mipmap.h_pdf_image, "Image PDF"),
)
}
}
\ No newline at end of file
package com.base.pdfoneread.ui.main
import android.annotation.SuppressLint
import android.graphics.Color
import androidx.core.view.updatePadding
import androidx.fragment.app.Fragment
import androidx.navigation.NavController
import androidx.navigation.fragment.NavHostFragment
import com.base.pdfoneread.R
import com.base.pdfoneread.databinding.ActivityMainBinding
import com.base.pdfoneread.ui.BaseActivity
import com.base.pdfoneread.bean.HomeUIBean.Companion.UI_TYPE_GRID
import com.base.pdfoneread.bean.HomeUIBean.Companion.UI_TYPE_LIST
import com.base.pdfoneread.utils.BarUtils
import com.base.pdfoneread.utils.SpannableUtils.colorSpanner
class MainActivity : BaseActivity<ActivityMainBinding>() {
override val binding: ActivityMainBinding by lazy {
ActivityMainBinding.inflate(layoutInflater)
}
var homeUiType = UI_TYPE_GRID
private lateinit var navController: NavController
override fun initView() {
BarUtils.setStatusBarLightMode(this, true)
BarUtils.setStatusBarColor(this, Color.WHITE)
binding.root.updatePadding(top = BarUtils.getStatusBarHeight())
val navHostFragment =
supportFragmentManager.findFragmentById(R.id.nav_host_container) as NavHostFragment
navController = navHostFragment.navController
changeHomeRvIcon()
}
override fun initListener() {
super.initListener()
binding.llHome.setOnClickListener {
changeHomeUI()
}
binding.llHome.callOnClick()
binding.llRecent.setOnClickListener {
changeRecentUI()
}
binding.llSetting.setOnClickListener {
changeSettingUI()
}
binding.flRvMode.setOnClickListener {
val currentFragment = getNavCurrentFragment()
if (currentFragment is HomeFragment) {
if (homeUiType == UI_TYPE_GRID) {
homeUiType = UI_TYPE_LIST
} else {
homeUiType = UI_TYPE_GRID
}
changeHomeRvIcon()
currentFragment.changeUIByMain()
}
}
}
private fun changeHomeRvIcon() {
if (homeUiType == UI_TYPE_LIST) {
binding.ivRvMode.setImageResource(R.mipmap.h_pdf_grid)
} else {
binding.ivRvMode.setImageResource(R.mipmap.h_pdf_list)
}
}
fun getNavCurrentFragment(): Fragment? {
val navHostFragment: Fragment = binding.navHostContainer.getFragment()
val currentFragment = navHostFragment.childFragmentManager.primaryNavigationFragment
return currentFragment
}
private fun disSelectTab() {
binding.ivHome.isSelected = false
binding.tvHome.isSelected = false
binding.ivRecent.isSelected = false
binding.tvRecent.isSelected = false
binding.ivSetting.isSelected = false
binding.tvSetting.isSelected = false
}
@SuppressLint("SetTextI18n")
private fun changeHomeUI() {
disSelectTab()
binding.ivHome.isSelected = true
binding.tvHome.isSelected = true
val appName = resources.getString(R.string.app_name)
binding.tvTittle.text = colorSpanner(appName, Color.parseColor("#FD1010"), 0, 3)
navController.popBackStack()
navController.navigate(R.id.homeFragment)
}
private fun changeRecentUI() {
disSelectTab()
binding.ivRecent.isSelected = true
binding.tvRecent.isSelected = true
binding.tvTittle.text = resources.getString(R.string.recent)
navController.popBackStack()
navController.navigate(R.id.recentFragment)
}
private fun changeSettingUI() {
disSelectTab()
binding.ivSetting.isSelected = true
binding.tvSetting.isSelected = true
binding.tvTittle.text = resources.getString(R.string.settings)
navController.popBackStack()
navController.navigate(R.id.settingFragment)
}
}
\ No newline at end of file
package com.base.pdfoneread.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.pdfoneread.R
class RecentFragment() : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_recent, container, false)
}
companion object {
}
}
\ No newline at end of file
package com.base.pdfoneread.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.pdfoneread.R
class SettingFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_setting, container, false)
}
companion object {
}
}
\ No newline at end of file
package com.base.pdfoneread.ui.splash
import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import com.base.pdfoneread.ui.main.MainActivity
import com.base.pdfoneread.utils.LogEx
import java.util.concurrent.atomic.AtomicBoolean
/**
* 适配官方启动页
* https://cloud.tencent.com/developer/ask/sof/915280
*/
class SystemStartActivity : AppCompatActivity() {
private val TAG = "SystemStartActivity"
// 数据
private var mKeepOnAtomicBool = AtomicBoolean(true)
override fun onCreate(savedInstanceState: Bundle?) {
// 初始化操作(必须放在setContentView()之前)
val splashScreen = installSplashScreen()
super.onCreate(savedInstanceState)
// setContentView(可以省略)
// setContentView(R.layout.activity_system_start)
// 每次UI绘制前,会判断 Splash 是否有必要继续展示在屏幕上;直到不再满足条件时,隐藏Splash。
splashScreen.setKeepOnScreenCondition {
mKeepOnAtomicBool.get()
}
LogEx.logDebug(TAG, "setKeepOnScreenCondition...")
startActivity(Intent(this@SystemStartActivity, MainActivity::class.java))
this@SystemStartActivity.finish()
overridePendingTransition(0, 0)
mKeepOnAtomicBool.compareAndSet(true, false)
// Splash动画展示完毕的监听方法,无动画不用
// splashScreen.setOnExitAnimationListener(object : SplashScreen.OnExitAnimationListener {
// override fun onSplashScreenExit(splashScreenViewProvider: SplashScreenViewProvider) {
// LogEx.logDebug(TAG, "onSplashScreenExit")
// startActivity(Intent(this@SystemStartActivity, MyStartActivity::class.java))
// this@SystemStartActivity.finish()
// overridePendingTransition(0, 0)
// mKeepOnAtomicBool.compareAndSet(true, false)
// }
// })
}
}
\ No newline at end of file
package com.base.pdfoneread.ui.views
import android.content.Context
import android.graphics.Color
import android.text.SpannableString
import android.text.Spanned
import android.text.style.ForegroundColorSpan
import android.view.LayoutInflater
import android.view.View
import com.base.pdfoneread.R
import com.base.pdfoneread.utils.ActivityLauncher
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()
// }
// val text = "To read and edit documents on your device, please allow PDF Reader to access all your files"
// val redText = "PDF Reader"
// val spannableString = SpannableString(text)
// val startIndex = text.indexOf(redText)
// val endIndex = startIndex + redText.length
//
// spannableString.setSpan(
// ForegroundColorSpan(Color.parseColor("#6DA9FD")),
// startIndex,
// endIndex,
// Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
// )
// binding.tvTip.text = spannableString
//
// return dialog
//
// }
}
\ No newline at end of file
package com.base.pdfoneread.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.pdfoneread.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.pdfoneread.utils;
import static com.base.pdfoneread.ui.MyApplication.appContext;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
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(appContext.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.pdfoneread.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.pdfoneread.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.pdfoneread.utils
import android.util.Log
object LogEx {
val isOpen = true
val filterTAG = arrayOf(
"",
// "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
This diff is collapsed.
//package com.base.pdfoneread.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.tom_roush.pdfbox.rendering.RenderDestination
//import java.io.File
//import java.io.IOException
//
//
//object PdfBoxUtils {
//
// private val TAG = "PdfUtils"
//
// fun getNumberOfPages(context: Context, filePath: String, password: String? = null, uri: String? = null): Int {
// val document = context.loadPDDocument(path = filePath, password, uri)
// return document.numberOfPages
// }
//
//
// fun getPdfDrawablePage(
// context: Context,
// filePath: String,
// password: String? = null,
// uri: String? = null,
// pageIndex: Int,
// scale: Float = 1f,
// ): Drawable {
// val document = context.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.pdfoneread.utils
import android.text.Spannable
import android.text.SpannableString
import android.text.style.ForegroundColorSpan
import androidx.annotation.ColorInt
object SpannableUtils {
fun colorSpanner(string: String, @ColorInt color: Int, start: Int, end: Int): SpannableString {
val spannableString = SpannableString(string)
spannableString.setSpan(ForegroundColorSpan(color), start, end, Spannable.SPAN_INCLUSIVE_INCLUSIVE)
return spannableString
}
}
\ No newline at end of file
package com.base.pdfoneread.utils
import android.content.Context
import android.widget.Toast
object ToastUtils {
fun Context.toast(content: String) {
Toast.makeText(this, content, Toast.LENGTH_SHORT).show()
}
}
\ No newline at end of file
package com.base.pdfoneread.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
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#FF1010" android:state_selected="true" />
<item android:color="#8E95A0" android:state_selected="false" />
</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_tob_home_s" android:state_selected="true" />
<item android:drawable="@mipmap/h_tob_home_n" android:state_selected="false" />
</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_tob_time_s" android:state_selected="true" />
<item android:drawable="@mipmap/h_tob_time_n" android:state_selected="false" />
</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_tob_settings_s" android:state_selected="true" />
<item android:drawable="@mipmap/h_tob_settings_n" 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
<?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.document.DocumentActivity">
</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.main.MainActivity">
<androidx.cardview.widget.CardView
android:id="@+id/card_top"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_top"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/tv_tittle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginVertical="24dp"
android:layout_marginStart="24dp"
android:textColor="@color/black"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="One Read" />
<FrameLayout
android:id="@+id/fl_search"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="15dp"
app:layout_constraintBottom_toBottomOf="@id/tv_tittle"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/tv_tittle">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/h_search"
tools:ignore="ContentDescription" />
</FrameLayout>
<FrameLayout
android:id="@+id/fl_rv_mode"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="15dp"
app:layout_constraintBottom_toBottomOf="@id/tv_tittle"
app:layout_constraintEnd_toStartOf="@id/fl_search"
app:layout_constraintTop_toTopOf="@id/tv_tittle">
<ImageView
android:id="@+id/iv_rv_mode"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/h_pdf_grid"
tools:ignore="ContentDescription" />
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_container"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
app:defaultNavHost="true"
app:layout_constraintBottom_toTopOf="@id/ll_bottom"
app:layout_constraintTop_toBottomOf="@id/card_top"
app:navGraph="@navigation/nav_main" />
<LinearLayout
android:id="@+id/ll_bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="60dp"
android:baselineAligned="false"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent">
<LinearLayout
android:id="@+id/ll_home"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical"
android:paddingTop="8dp"
android:paddingBottom="8dp"
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/bg_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="6dp"
android:text="@string/home"
android:textColor="@color/color_selector_tab" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_recent"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical"
android:paddingTop="8dp"
android:paddingBottom="8dp"
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/bg_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="6dp"
android:text="@string/recent"
android:textColor="@color/color_selector_tab" />
</LinearLayout>
<LinearLayout
android:id="@+id/ll_setting"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical"
android:paddingTop="8dp"
android:paddingBottom="8dp"
tools:ignore="UseCompoundDrawables">
<ImageView
android:id="@+id/iv_setting"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="@drawable/bg_selector_setting"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/tv_setting"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="6dp"
android:text="@string/settings"
android:textColor="@color/color_selector_tab" />
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
\ 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"
android:background="@color/white"
tools:context=".ui.main.HomeFragment">
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/swipeRefreshLayout"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:spanCount="4"
tools:listitem="@layout/item_home_grid" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</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:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.main.RecentFragment">
</FrameLayout>
\ 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:background="@color/white"
android:orientation="vertical"
tools:context=".ui.main.SettingFragment">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginVertical="20dp"
android:layout_marginStart="24dp"
android:src="@mipmap/s_pdf_file"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginHorizontal="28dp"
android:layout_weight="1"
android:text="@string/file_manager"
android:textColor="@color/black"
android:textSize="14sp"
android:textStyle="bold" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|end"
android:layout_marginEnd="38dp"
android:src="@mipmap/h_pdf__right"
tools:ignore="ContentDescription" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginVertical="20dp"
android:layout_marginStart="24dp"
android:src="@mipmap/s_pdf_set"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginHorizontal="28dp"
android:layout_weight="1"
android:text="@string/set_as_default"
android:textColor="@color/black"
android:textSize="14sp"
android:textStyle="bold" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|end"
android:layout_marginEnd="38dp"
android:src="@mipmap/h_pdf__right"
tools:ignore="ContentDescription" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginVertical="20dp"
android:layout_marginStart="24dp"
android:src="@mipmap/s_pdf_ev"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginHorizontal="28dp"
android:layout_weight="1"
android:text="@string/evaluage_options"
android:textColor="@color/black"
android:textSize="14sp"
android:textStyle="bold" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|end"
android:layout_marginEnd="38dp"
android:src="@mipmap/h_pdf__right"
tools:ignore="ContentDescription" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginVertical="20dp"
android:layout_marginStart="24dp"
android:src="@mipmap/s_pdf_feedback"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginHorizontal="28dp"
android:layout_weight="1"
android:text="@string/feedback"
android:textColor="@color/black"
android:textSize="14sp"
android:textStyle="bold" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|end"
android:layout_marginEnd="38dp"
android:src="@mipmap/h_pdf__right"
tools:ignore="ContentDescription" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginVertical="20dp"
android:layout_marginStart="24dp"
android:src="@mipmap/s_pdf_privacy"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginHorizontal="28dp"
android:layout_weight="1"
android:text="@string/privacy_policy"
android:textColor="@color/black"
android:textSize="14sp"
android:textStyle="bold" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|end"
android:layout_marginEnd="38dp"
android:src="@mipmap/h_pdf__right"
tools:ignore="ContentDescription" />
</LinearLayout>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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="wrap_content"
android:orientation="vertical">
<ImageView
android:id="@+id/iv_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="8dp"
tools:ignore="ContentDescription"
tools:src="@mipmap/h_pdf_all" />
<TextView
android:id="@+id/tv_des"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:textColor="@color/black"
android:textSize="12sp"
android:textStyle="bold"
tools:text="All" />
<TextView
android:id="@+id/tv_file_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="8dp"
android:visibility="gone"
tools:text="35 files" />
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/iv_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginVertical="16dp"
android:layout_marginStart="21dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription"
tools:src="@mipmap/h_pdf_all" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="30dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="@id/iv_icon"
app:layout_constraintEnd_toStartOf="@id/iv_arrow"
app:layout_constraintStart_toEndOf="@id/iv_icon"
app:layout_constraintTop_toTopOf="@id/iv_icon">
<TextView
android:id="@+id/tv_des"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/black"
android:textSize="16sp"
tools:text="All" />
<TextView
android:id="@+id/tv_file_number"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:textColor="#979DA7"
android:textSize="14sp"
tools:ignore="HardcodedText"
tools:text="43 files" />
</LinearLayout>
<ImageView
android:id="@+id/iv_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="32dp"
android:src="@mipmap/h_pdf__right"
app:layout_constraintBottom_toBottomOf="@id/iv_icon"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/iv_icon"
tools:ignore="ContentDescription" />
<View
android:layout_width="0dp"
android:layout_height="0.25dp"
android:layout_marginStart="40dp"
android:layout_marginEnd="15dp"
android:background="#C4C4C4"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
</androidx.recyclerview.widget.RecyclerView>
\ 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:layout_width="match_parent"
android:id="@+id/tv_tittle"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="20dp"
android:layout_marginBottom="20dp"
android:textColor="#8E95A0"
android:textSize="15sp"
tools:text="Tools" />
<?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/home.xml"
app:startDestination="@id/homeFragment">
<fragment
android:id="@+id/homeFragment"
android:name="com.base.pdfoneread.ui.main.HomeFragment"
android:label="fragment_home"
tools:layout="@layout/fragment_home" />
<fragment
android:id="@+id/recentFragment"
android:name="com.base.pdfoneread.ui.main.RecentFragment"
android:label="fragment_recent"
tools:layout="@layout/fragment_recent" />
<fragment
android:id="@+id/settingFragment"
android:name="com.base.pdfoneread.ui.main.SettingFragment"
android:label="fragment_setting"
tools:layout="@layout/fragment_setting" />
</navigation>
\ No newline at end of file
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Base.Theme.PdfOneRead" 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
<?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>
<string name="app_name">PDF Reader &amp; PDF Editor</string>
<string name="home">Home</string>
<string name="recent">Recent</string>
<string name="settings">Settings</string>
<string name="file_manager">File Manager</string>
<string name="set_as_default">Set as Default</string>
<string name="evaluage_options">Evaluage Options</string>
<string name="feedback">Feedback</string>
<string name="privacy_policy">Privacy Policy</string>
<!-- TODO: Remove or change this placeholder text -->
<string name="hello_blank_fragment">Hello blank fragment</string>
</resources>
\ No newline at end of file
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Base.Theme.PdfOneRead" parent="Theme.AppCompat.DayNight.NoActionBar" />
<style name="Theme.PdfOneRead" parent="Base.Theme.PdfOneRead" />
<style name="Theme.App.Starting" parent="Theme.SplashScreen">
<!--启动画面背景颜色-->
<item name="windowSplashScreenBackground">@color/white</item>
<!-- <item name="android:windowBackground">@drawable/splash_bp</item>-->
<!-- 启动画面icon图标:这里可以是图片、帧动画等-->
<item name="windowSplashScreenAnimatedIcon">@drawable/ic_launcher_foreground</item>
<item name="splashScreenIconSize">50dp</item>
<item name="windowSplashScreenIconBackgroundColor">@android:color/transparent</item>
<!-- icon动画在关闭之前显示的时长:最长时间为1000毫秒-->
<item name="windowSplashScreenAnimationDuration">100</item>
<!-- Splash退出后的主题-->
<item name="postSplashScreenTheme">@style/Theme.PdfOneRead</item>
</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
// 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
}
\ 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"
swiperefreshlayout = "1.1.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-swiperefreshlayout = { group = "androidx.swiperefreshlayout", name = "swiperefreshlayout", version.ref = "swiperefreshlayout" }
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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