This commit is contained in:
ocean 2025-12-16 14:00:03 +08:00
parent 3ad4c5e916
commit 544fe96be5
12 changed files with 234 additions and 82 deletions

View File

@ -150,6 +150,12 @@
android:label="@string/app_name"
android:screenOrientation="portrait" />
<activity
android:name=".ui.act.PictureSelectorCameraActivity"
android:exported="true"
android:label="@string/app_name"
android:screenOrientation="portrait" />
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"

View File

@ -29,6 +29,13 @@ class AdInstShower(
val errorMsg = "广告展示过于频繁, 请等待 ${(SHOW_INTERVAL - (now - lastShowTimestamp)) / 1000}s间隔限制60s"
showListener?.onAdShowFailed(errorMsg)
Log.d(AdsInsUtil.Placement.TAG, "showAd->$errorMsg")
AnalyticsUtils.logAdEvent(
placement,
AnalyticsUtils.AdEvent.SHOW_FAIL_ME,
1001,
errorMsg
)
return
}
}
@ -38,6 +45,13 @@ class AdInstShower(
val errorMsg = "插页式广告缓存为空 = $placement"
showListener?.onAdShowFailed(errorMsg)
Log.d(AdsInsUtil.Placement.TAG, "showAd->$errorMsg")
AnalyticsUtils.logAdEvent(
placement,
AnalyticsUtils.AdEvent.SHOW_FAIL_ME,
1002,
errorMsg
)
return
}

View File

@ -489,6 +489,7 @@ class PdfViewActivity : BaseActivity(), OnLoadCompleteListener, OnPageChangeList
setSelection(0)
}
} else {
AnalyticsUtils.logEvent(AnalyticsUtils.Event.PDFTO_HOME_CK)
AdsInsUtil.showFinishAd(
this@PdfViewActivity,
AdsInsUtil.AdPlacement.INT_AND_PDFTOHOME

View File

@ -1,11 +1,9 @@
package com.all.pdfreader.pdf.reader.ui.act
import android.content.Context
import android.net.Uri
import android.os.Bundle
import android.view.View
import androidx.core.net.toUri
import androidx.fragment.app.Fragment
import com.all.pdfreader.pdf.reader.PRApp
import com.all.pdfreader.pdf.reader.R
import com.all.pdfreader.pdf.reader.databinding.ActPictureSelectorBinding
@ -18,8 +16,6 @@ import com.luck.picture.lib.config.SelectMimeType
import com.luck.picture.lib.config.SelectModeConfig
import com.luck.picture.lib.engine.CompressFileEngine
import com.luck.picture.lib.entity.LocalMedia
import com.luck.picture.lib.interfaces.OnKeyValueResultCallbackListener
import com.luck.picture.lib.interfaces.OnMediaEditInterceptListener
import com.luck.picture.lib.interfaces.OnResultCallbackListener
import com.luck.picture.lib.style.PictureSelectorStyle
import com.luck.picture.lib.style.SelectMainStyle
@ -64,58 +60,47 @@ class PictureSelectorActivity : BaseActivity() {
.setSelectionMode(SelectModeConfig.MULTIPLE)
.setMaxSelectNum(50)
.isPreviewFullScreenMode(false)
.setCompressEngine(object : CompressFileEngine {
override fun onStartCompress(
context: Context?,
source: ArrayList<Uri?>?,
call: OnKeyValueResultCallbackListener?
) {
Luban.with(context)
.load(source)
.ignoreBy(100)
.setCompressListener(object : OnNewCompressListener {
override fun onStart() {
.setCompressEngine(CompressFileEngine { context, source, call ->
Luban.with(context)
.load(source)
.ignoreBy(100)
.setCompressListener(object : OnNewCompressListener {
override fun onStart() {
}
}
override fun onSuccess(
source: String?,
compressFile: File?
) {
call?.onCallback(source, compressFile?.absolutePath)
}
override fun onSuccess(
source: String?,
compressFile: File?
) {
call?.onCallback(source, compressFile?.absolutePath)
}
override fun onError(source: String?, e: Throwable?) {
call?.onCallback(source, null)
}
})
.launch()
}
override fun onError(source: String?, e: Throwable?) {
call?.onCallback(source, null)
}
})
.launch()
})
.setEditMediaInterceptListener(object : OnMediaEditInterceptListener {
override fun onStartMediaEdit(
fragment: Fragment, currentLocalMedia: LocalMedia, requestCode: Int
) {
val currentEditPath = currentLocalMedia.getAvailablePath()
val inputUri = if (PictureMimeType.isContent(currentEditPath)) {
currentEditPath.toUri()
} else {
Uri.fromFile(File(currentEditPath))
}
val destinationUri = Uri.fromFile(
File(
getSandboxPath(), DateUtils.getCreateFileName("CROP_") + ".jpeg"
)
)
val uCrop = UCrop.of<Any>(inputUri, destinationUri)
val buildOptions = UCrop.Options().apply {
isDarkStatusBarBlack(true)
}
uCrop.withOptions(buildOptions)
uCrop.start(this@PictureSelectorActivity, fragment, requestCode)
.setEditMediaInterceptListener { fragment, currentLocalMedia, requestCode ->
val currentEditPath = currentLocalMedia.getAvailablePath()
val inputUri = if (PictureMimeType.isContent(currentEditPath)) {
currentEditPath.toUri()
} else {
Uri.fromFile(File(currentEditPath))
}
}).buildLaunch(R.id.fragment_container,object : OnResultCallbackListener<LocalMedia>{
val destinationUri = Uri.fromFile(
File(
getSandboxPath(), DateUtils.getCreateFileName("CROP_") + ".jpeg"
)
)
val uCrop = UCrop.of<Any>(inputUri, destinationUri)
val buildOptions = UCrop.Options().apply {
isDarkStatusBarBlack(true)
}
uCrop.withOptions(buildOptions)
uCrop.start(this@PictureSelectorActivity, fragment, requestCode)
}.buildLaunch(R.id.fragment_container,object : OnResultCallbackListener<LocalMedia>{
override fun onResult(result: ArrayList<LocalMedia>) {
logDebug("forResult ->${result.size}")
if (result.isNotEmpty()) {

View File

@ -0,0 +1,88 @@
package com.all.pdfreader.pdf.reader.ui.act
import android.os.Bundle
import android.view.View
import com.all.pdfreader.pdf.reader.R
import com.all.pdfreader.pdf.reader.databinding.ActPictureSelectorBinding
import com.all.pdfreader.pdf.reader.model.PdfPickerSource
import com.all.pdfreader.pdf.reader.util.AnalyticsUtils
import com.luck.picture.lib.basic.PictureSelector
import com.luck.picture.lib.config.SelectMimeType
import com.luck.picture.lib.engine.CompressFileEngine
import com.luck.picture.lib.entity.LocalMedia
import com.luck.picture.lib.interfaces.OnResultCallbackListener
import top.zibin.luban.Luban
import top.zibin.luban.OnNewCompressListener
import java.io.File
class PictureSelectorCameraActivity : BaseActivity() {
private lateinit var binding: ActPictureSelectorBinding
override val rootBottomView: View
get() = binding.rootBottomLayout
override val TAG = "PictureSelectorCameraActivity"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActPictureSelectorBinding.inflate(layoutInflater)
setContentView(binding.root)
AnalyticsUtils.logEvent(AnalyticsUtils.Event.SCAN_TO_PDF_SHOW)
setupImmersionBar {
statusBarView(binding.view)
statusBarDarkFont(false)
}
openImagePicker()
}
private fun openImagePicker() {
PictureSelector.create(this)
.openCamera(SelectMimeType.ofImage())
.setCompressEngine(CompressFileEngine { context, source, call ->
Luban.with(context)
.load(source)
.ignoreBy(100)
.setCompressListener(object : OnNewCompressListener {
override fun onStart() {
}
override fun onSuccess(
source: String?,
compressFile: File?
) {
call?.onCallback(source, compressFile?.absolutePath)
}
override fun onError(source: String?, e: Throwable?) {
call?.onCallback(source, null)
}
})
.launch()
})
.buildLaunch(R.id.fragment_container, object : OnResultCallbackListener<LocalMedia> {
override fun onResult(result: ArrayList<LocalMedia>) {
logDebug("forResult ->${result.size}")
if (result.isNotEmpty()) {
// result 中可能有带裁剪的 Uri 或原图 Uri
// 取出路径列表
val paths = result.mapNotNull { media ->
media.availablePath
}
if (paths.isEmpty()) {
return
}
val intent = PdfResultActivity.createIntentInputFile(
this@PictureSelectorCameraActivity,
ArrayList(paths),
PdfPickerSource.IMAGES_TO_PDF
)
startActivity(intent)
finish()
}
}
override fun onCancel() {
finish()
}
})
}
}

View File

@ -9,6 +9,7 @@ import com.all.pdfreader.pdf.reader.databinding.FragmentToolsBinding
import com.all.pdfreader.pdf.reader.model.PdfPickerSource
import com.all.pdfreader.pdf.reader.ui.act.PdfPickerActivity
import com.all.pdfreader.pdf.reader.ui.act.PictureSelectorActivity
import com.all.pdfreader.pdf.reader.ui.act.PictureSelectorCameraActivity
class ToolsFrag : BaseFrag() {
override val TAG: String = "ToolsFrag"
@ -59,5 +60,9 @@ class ToolsFrag : BaseFrag() {
val intent = PdfPickerActivity.createIntent(requireActivity(), PdfPickerSource.PRINT)
startActivity(intent)
}
binding.scanToPdfBtn.setOnClickListener {
val intent = Intent(requireActivity(), PictureSelectorCameraActivity::class.java)
startActivity(intent)
}
}
}

View File

@ -96,6 +96,10 @@ object AnalyticsUtils {
const val UNLOCK_SUCCESS = "unlock_success" // 解锁成功unlock_success
const val KEEP_SCREEN_OPEN = "keep_screen_open" // 点击打开keep_screen_open
const val KEEP_SCREEN_CLOSE = "keep_screen_close" // 点击关闭keep_screen_close
const val SHARE = "share"//所有分享文件的操作
const val PRINT = "print"//所有打印
const val PDFTO_HOME_CK = "pdfto_home_ck"//pdf阅读页响应返回
const val SCAN_TO_PDF_SHOW = "scan_to_pdf_show" //扫描成pdf功能界面
}
/** param 常量(可扩展) */
@ -112,6 +116,7 @@ object AnalyticsUtils {
LOAD_FAIL("load_fail_header"),
SHOW_SUC("show_suc_header"),
SHOW_FAIL("show_fail_header"),
SHOW_FAIL_ME("show_fail_me_header"),//记录自定义的错误信息
}
/** 统一广告打点 */

View File

@ -115,6 +115,7 @@ object AppUtils {
* @param file 要分享的文件
*/
fun shareFile(context: Context, file: File) {
AnalyticsUtils.logEvent(AnalyticsUtils.Event.SHARE)
try {
if (!file.exists()) {
ToastUtils.show(context, context.getString(R.string.error_file_not_exist))
@ -150,6 +151,7 @@ object AppUtils {
* @param files 要分享的文件列表
*/
fun shareMultipleFiles(context: Context, files: List<File>) {
AnalyticsUtils.logEvent(AnalyticsUtils.Event.SHARE)
try {
if (files.isEmpty()) {
ToastUtils.show(context, context.getString(R.string.error_file_not_exist))
@ -214,6 +216,7 @@ object AppUtils {
* @return PrintResult 打印结果的状态成功密码保护设备不支持等
*/
fun printPdfFile(context: Context, uri: Uri?): PrintResult {
AnalyticsUtils.logEvent(AnalyticsUtils.Event.PRINT)
return try {
// 打开文件描述符,用于访问 PDF 文件内容
val pd = context.contentResolver.openFileDescriptor(

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="20dp"/>
<solid android:color="#F5FFF3"/>
</shape>

View File

@ -0,0 +1,34 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="30dp"
android:height="30dp"
android:viewportWidth="30"
android:viewportHeight="30">
<group>
<clip-path
android:pathData="M0,0h30v30h-30z"/>
<path
android:pathData="M0.833,10V1.98C0.834,1.676 0.955,1.385 1.169,1.17C1.384,0.955 1.675,0.834 1.979,0.833H10V3.125H3.124V10H0.833Z"
android:fillColor="#77FF00"/>
<path
android:pathData="M19.167,3.125H26.666V10H29.167V1.98C29.166,1.676 29.034,1.384 28.8,1.169C28.565,0.954 28.247,0.833 27.915,0.833H19.167V3.125Z"
android:fillColor="#77FF00"/>
<path
android:pathData="M26.666,20V26.876H19.167V29.167H27.921C28.253,29.165 28.57,29.042 28.804,28.826C29.037,28.61 29.168,28.318 29.167,28.014V20H26.666Z"
android:fillColor="#77FF00"/>
<path
android:pathData="M10,26.882H3.124V20H0.833V28.02C0.834,28.324 0.955,28.615 1.17,28.83C1.384,29.045 1.675,29.166 1.979,29.167H10V26.882Z"
android:fillColor="#77FF00"/>
<path
android:pathData="M29.167,14.167H23.333V15.834H29.167V14.167Z"
android:fillColor="#77FF00"/>
<path
android:pathData="M7.5,14.167H0.833V15.834H7.5V14.167Z"
android:fillColor="#77FF00"/>
<path
android:pathData="M22.779,12.5H23.333V8.616C23.333,8.099 23.119,7.603 22.738,7.238C22.357,6.872 21.841,6.667 21.302,6.667H9.528C8.99,6.668 8.474,6.874 8.094,7.239C7.714,7.605 7.5,8.1 7.5,8.616V12.5H22.779Z"
android:fillColor="#77FF00"/>
<path
android:pathData="M22.779,14.167H7.5V22.178C7.5,22.439 7.553,22.698 7.655,22.939C7.757,23.181 7.906,23.4 8.095,23.585C8.284,23.77 8.508,23.916 8.754,24.016C9.001,24.116 9.265,24.167 9.531,24.167H21.302C21.569,24.167 21.833,24.116 22.079,24.016C22.326,23.916 22.55,23.77 22.738,23.585C22.927,23.4 23.076,23.181 23.179,22.939C23.281,22.698 23.333,22.439 23.333,22.178V14.167H22.779Z"
android:fillColor="#77FF00"/>
</group>
</vector>

View File

@ -117,6 +117,37 @@
android:layout_marginBottom="16dp"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/scanToPdfBtn"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<LinearLayout
android:layout_width="60dp"
android:layout_height="60dp"
android:background="@drawable/drw_tools_scan_bg"
android:gravity="center">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/tools_scan_to_pdf_img" />
</LinearLayout>
<TextView
style="@style/TextViewFont_PopMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="@string/scan_to_pdf"
android:textColor="@color/text_color_lv1"
android:textSize="12sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/mergeBtn"
android:layout_width="0dp"
@ -177,35 +208,6 @@
android:textSize="12sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/printBtn"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">
<LinearLayout
android:layout_width="60dp"
android:layout_height="60dp"
android:background="@drawable/drw_tools_print_bg"
android:gravity="center">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/tools_print" />
</LinearLayout>
<TextView
style="@style/TextViewFont_PopMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="@string/print_pdf"
android:textColor="@color/text_color_lv1"
android:textSize="12sp" />
</LinearLayout>
</LinearLayout>
@ -277,12 +279,12 @@
</LinearLayout>
<LinearLayout
android:id="@+id/printBtn"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical"
android:visibility="invisible">
android:orientation="vertical">
<LinearLayout
android:layout_width="60dp"

View File

@ -197,4 +197,5 @@
<string name="processing_failed">Processing failed</string>
<string name="tap_again_to_exit">Tap again to exit</string>
<string name="ad_attribution" translatable="false">Ad</string>
<string name="scan_to_pdf">Scan to PDF</string>
</resources>