Save PDF and share it
This commit is contained in:
@@ -28,6 +28,15 @@
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${applicationId}.fileprovider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/file_paths" />
|
||||
</provider>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -1,7 +1,11 @@
|
||||
package org.mydomain.myscan
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Bitmap
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
@@ -17,13 +21,16 @@ import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.content.FileProvider
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import org.mydomain.myscan.ui.theme.MyScanTheme
|
||||
import org.mydomain.myscan.view.CameraScreen
|
||||
import org.mydomain.myscan.view.PagePreviewScreen
|
||||
import org.opencv.android.OpenCVLoader
|
||||
import java.io.File
|
||||
|
||||
class MainActivity : ComponentActivity() {
|
||||
|
||||
@@ -37,6 +44,7 @@ class MainActivity : ComponentActivity() {
|
||||
val currentScreen by viewModel.currentScreen.collectAsState()
|
||||
// TODO should uiState own currentScreen?
|
||||
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
|
||||
val context = LocalContext.current
|
||||
MyScanTheme {
|
||||
Scaffold { innerPadding ->
|
||||
Column {
|
||||
@@ -51,7 +59,8 @@ class MainActivity : ComponentActivity() {
|
||||
PagePreviewScreen (
|
||||
image = screen.image,
|
||||
isProcessing = screen.isProcessing,
|
||||
onBackPressed = { viewModel.navigateTo(Screen.Camera) }
|
||||
onBackPressed = { viewModel.navigateTo(Screen.Camera) },
|
||||
onSavePressed = createPdfAndShare(context)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -61,6 +70,27 @@ class MainActivity : ComponentActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun createPdfAndShare(context: Context): (Bitmap) -> Unit = { bitmap ->
|
||||
val outputDir = File(cacheDir, "pdfs").apply { mkdirs() }
|
||||
val outputFile = File(outputDir, "scan_${System.currentTimeMillis()}.pdf")
|
||||
val success = createPdfFromBitmaps(listOf(bitmap), outputFile)
|
||||
if (success) {
|
||||
val uri = FileProvider.getUriForFile(
|
||||
context,
|
||||
"${applicationContext.packageName}.fileprovider",
|
||||
outputFile
|
||||
)
|
||||
val shareIntent = Intent(Intent.ACTION_SEND).apply {
|
||||
type = "application/pdf"
|
||||
putExtra(Intent.EXTRA_STREAM, uri)
|
||||
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
}
|
||||
startActivity(Intent.createChooser(shareIntent, "Share PDF"))
|
||||
} else {
|
||||
Toast.makeText(context, "Failed to save PDF", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
private fun initOpenCV() {
|
||||
if (!OpenCVLoader.initLocal()) {
|
||||
Log.e("OpenCV", "Initialization failed")
|
||||
|
||||
29
app/src/main/java/org/mydomain/myscan/PdfGeneration.kt
Normal file
29
app/src/main/java/org/mydomain/myscan/PdfGeneration.kt
Normal file
@@ -0,0 +1,29 @@
|
||||
package org.mydomain.myscan
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.pdf.PdfDocument
|
||||
import android.util.Log
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.io.IOException
|
||||
|
||||
fun createPdfFromBitmaps(bitmaps: List<Bitmap>, outputFile: File): Boolean {
|
||||
val document = PdfDocument()
|
||||
try {
|
||||
for ((index, bitmap) in bitmaps.withIndex()) {
|
||||
val pageInfo = PdfDocument.PageInfo.Builder(bitmap.width, bitmap.height, index + 1).create()
|
||||
val page = document.startPage(pageInfo)
|
||||
page.canvas.drawBitmap(bitmap, 0f, 0f, null)
|
||||
document.finishPage(page)
|
||||
}
|
||||
FileOutputStream(outputFile).use { outputStream ->
|
||||
document.writeTo(outputStream)
|
||||
}
|
||||
return true
|
||||
} catch (e: IOException) {
|
||||
Log.e("MyScan", "Error writing PDF: ${e.message}")
|
||||
return false
|
||||
} finally {
|
||||
document.close()
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
@@ -22,7 +23,8 @@ import androidx.compose.ui.unit.dp
|
||||
fun PagePreviewScreen(
|
||||
image: Bitmap?,
|
||||
isProcessing: Boolean,
|
||||
onBackPressed: () -> Unit
|
||||
onBackPressed: () -> Unit,
|
||||
onSavePressed: (Bitmap) -> Unit,
|
||||
) {
|
||||
Box(modifier = Modifier.fillMaxSize()) {
|
||||
when {
|
||||
@@ -39,6 +41,14 @@ fun PagePreviewScreen(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
contentScale = ContentScale.Fit
|
||||
)
|
||||
Button (
|
||||
onClick = { onSavePressed(image) },
|
||||
modifier = Modifier
|
||||
.align(Alignment.BottomCenter)
|
||||
.padding(16.dp)
|
||||
) {
|
||||
Text("Save as PDF")
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
Text(
|
||||
|
||||
6
app/src/main/res/xml/file_paths.xml
Normal file
6
app/src/main/res/xml/file_paths.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<paths xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<cache-path
|
||||
name="pdfs"
|
||||
path="pdfs/" />
|
||||
</paths>
|
||||
Reference in New Issue
Block a user