diff --git a/README.md b/README.md
index 74b97ca..5a94343 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,9 @@ Minimum Viable Goals:
- [x] Presentation View - i.e. show on an external monitor - haven't seen another app do this yet!
- [x] Immersive View - no system status bar etc.
- [x] Autocrop margins
-- [ ] Open files the Android way - currently just a bundled test file
+- [ ] Open files the Android way
+- - [x] Accept intents to load a single PDF
+- - [ ] Built-in file browser with requisite permissions
- [ ] Delete+Reorder Pages - doesn't have to save the source file, but does need to save a change journal
- - [x] Tap thumbnails to hide/show pages
- - [ ] Drag thumbnails to rearrange pages
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index edb436f..b8a1c14 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -16,12 +16,17 @@
android:name=".MainActivity"
android:exported="true"
android:label="@string/app_name"
+ android:launchMode="singleInstance"
android:theme="@style/Theme.PDFcast.NoActionBar">
-
+
+
+
+
+
diff --git a/app/src/main/java/com/lhw/pdf/MainActivity.kt b/app/src/main/java/com/lhw/pdf/MainActivity.kt
index 4b6e2d7..5ebca8c 100644
--- a/app/src/main/java/com/lhw/pdf/MainActivity.kt
+++ b/app/src/main/java/com/lhw/pdf/MainActivity.kt
@@ -1,17 +1,12 @@
package com.lhw.pdf
-import android.app.Presentation
import android.content.Context
+import android.content.Intent
import android.graphics.PorterDuff
import android.media.MediaRouter
import android.os.Bundle
-import android.util.DisplayMetrics
-import android.view.Display
import android.view.Menu
-import android.view.WindowManager
-import android.widget.HorizontalScrollView
import android.widget.ImageView
-import android.widget.LinearLayout
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.navigation.NavigationView
import androidx.navigation.findNavController
@@ -33,15 +28,15 @@ import kotlin.math.min
class MainActivity : AppCompatActivity() {
private lateinit var appBarConfiguration: AppBarConfiguration
private lateinit var binding: ActivityMainBinding
+ private lateinit var mediaRouter: MediaRouter
private val thumbnailWidth = 500
private val thumbnailHeight = 700
private var renderAutoCrop = true
private var pagesPerLandscape = 3F
- private val presentationDisplayMetrics = DisplayMetrics()
+ private var presentation: MyPresentation? = null
private lateinit var pdfDocument: PdfDocument
- private lateinit var presentationScroll: HorizontalScrollView
- private lateinit var presentationLayout: LinearLayout
private val showPages = mutableListOf()
+ private val defaultCachedFileName = "cached.pdf"
private fun inputStreamToCache(outputFilename: String, inputStream: InputStream): File {
val fileCached = File(cacheDir, outputFilename)
@@ -54,66 +49,31 @@ class MainActivity : AppCompatActivity() {
return fileCached
}
- private fun initializePdfDocument() {
- val inputStream = resources.openRawResource(R.raw.testpdf)
- pdfDocument = PdfDocument(inputStreamToCache("cached.pdf", inputStream), true)
- }
-
- class MyPresentation(outerContext: Context, display: Display) : Presentation(outerContext, display) {
-
- }
-
- private fun updatePresentationImages(rerender: Boolean = true) {
- if (rerender) {
- val maxHeight: Int = presentationDisplayMetrics.heightPixels
- val maxWidth: Int = min(maxHeight*5/7, (presentationDisplayMetrics.widthPixels/pagesPerLandscape).toInt())
- pdfDocument.renderPagesPresentation(maxWidth, maxHeight, renderAutoCrop)
- }
- presentationLayout.removeAllViewsInLayout()
- showPages.withIndex().filter { (i, show) -> (show) }.forEach { (i, show) ->
- val bitmap = pdfDocument.bitmapPagesPresentation[i]
- val img = ImageView(this)
- img.setImageBitmap(bitmap)
- presentationLayout.addView(img)
- }
- }
-
- private fun presentationView() {
- val mediaRouter = getSystemService(Context.MEDIA_ROUTER_SERVICE) as MediaRouter
- val presentationDisplay = mediaRouter.getSelectedRoute(MediaRouter.ROUTE_TYPE_LIVE_VIDEO)?.presentationDisplay
- if (presentationDisplay != null) {
- val presentation = MyPresentation(this, presentationDisplay)
- when (val pw = presentation.window) {
- null -> {}
- else -> {
- WindowCompat.getInsetsController(pw, pw.decorView).hide(WindowInsetsCompat.Type.systemBars())
- }
+ private fun updatePresentationImages(reRender: Boolean = true) {
+ presentation?.let { p ->
+ if (reRender) {
+ println(p.displayMetrics)
+ val maxHeight: Int = p.displayMetrics.heightPixels
+ val maxWidth: Int = min(maxHeight * 5 / 7, (p.displayMetrics.widthPixels / pagesPerLandscape).toInt())
+ println("Rendering pages with maxHeight=$maxHeight maxWidth=$maxWidth")
+ pdfDocument.renderPagesPresentation(maxWidth, maxHeight, renderAutoCrop)
}
-
- @Suppress("DEPRECATION")
- presentationDisplay.getMetrics(presentationDisplayMetrics)
- presentationLayout = LinearLayout(presentation.context)
- presentationScroll = HorizontalScrollView(presentation.context)
- presentationScroll.addView(presentationLayout)
- val layoutParams = WindowManager.LayoutParams()
- presentation.addContentView(presentationScroll, layoutParams)
- updatePresentationImages()
- presentation.show()
+ val bitmaps = showPages.withIndex()
+ .mapNotNull { (i, show) -> if (show) pdfDocument.bitmapPagesPresentation[i] else null }
+ .toList()
+ p.updateImages(bitmaps)
}
}
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- val windowInsetsController = WindowCompat.getInsetsController(window, window.decorView)
- windowInsetsController.hide(WindowInsetsCompat.Type.systemBars())
+ private fun makePresentationView() {
+ mediaRouter.getSelectedRoute(MediaRouter.ROUTE_TYPE_LIVE_VIDEO)?.presentationDisplay?.let { display ->
+ presentation = MyPresentation(this, display)
+ updatePresentationImages()
+ presentation?.show()
+ }
+ }
- binding = ActivityMainBinding.inflate(layoutInflater)
- setContentView(binding.root)
-
- setSupportActionBar(binding.appBarMain.toolbar)
-
- initializePdfDocument()
- pdfDocument.renderThumbnails(thumbnailWidth, thumbnailHeight)
+ private fun populateThumbnails() {
val container = binding.appBarMain.contentMain.thumbnailsLayout
for ((index, bitmap) in pdfDocument.bitmapThumbnails) {
val img = ImageView(this)
@@ -126,14 +86,36 @@ class MainActivity : AppCompatActivity() {
container.addView(img)
showPages.add(true)
}
- presentationView()
+ }
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ mediaRouter = getSystemService(Context.MEDIA_ROUTER_SERVICE) as MediaRouter
+ //val windowInsetsController = WindowCompat.getInsetsController(window, window.decorView)
+ //windowInsetsController.hide(WindowInsetsCompat.Type.systemBars()) //Doesn't seem to actually fill the vacant space by default
+
+ binding = ActivityMainBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+
+ setSupportActionBar(binding.appBarMain.toolbar)
+
+ // Load previous pdf, or included test pdf first
+ var file = File(cacheDir, defaultCachedFileName)
+ if (!file.exists()) {
+ file = inputStreamToCache(defaultCachedFileName, resources.openRawResource(R.raw.testpdf))
+ }
+ pdfDocument = PdfDocument(file, true)
+ // Then overwrite it with any pdf sent via intent
+ handleIntent(intent)
+
+ pdfDocument.renderThumbnails(thumbnailWidth, thumbnailHeight)
+ populateThumbnails()
+ makePresentationView()
+
+ val container = binding.appBarMain.contentMain.thumbnailsLayout
val containerScroll = binding.appBarMain.contentMain.thumbnailsScroll
containerScroll.viewTreeObserver.addOnScrollChangedListener {
- presentationScroll.scrollTo(
- containerScroll.scrollX * (presentationLayout.width - presentationScroll.width) / (container.width - containerScroll.width),
- 0
- )
+ presentation?.setScrollProgress(containerScroll.scrollX.toFloat() / (container.width - containerScroll.width))
}
binding.appBarMain.crop.setOnClickListener { view ->
@@ -172,6 +154,22 @@ class MainActivity : AppCompatActivity() {
navView.setupWithNavController(navController)
}
+ private fun handleIntent(intent: Intent?) {
+ val uri = intent?.data
+ if (uri == null) {
+ println("null intent uri passed")
+ return
+ }
+ println("intent uri passed: $uri")
+ // Do something with the URI to load PDF file
+ pdfDocument = contentResolver.openInputStream(uri)?.let { PdfDocument(inputStreamToCache(defaultCachedFileName, it), true) } ?: pdfDocument
+ }
+
+ override fun onNewIntent(intent: Intent?) {
+ super.onNewIntent(intent)
+ handleIntent(intent)
+ }
+
override fun onCreateOptionsMenu(menu: Menu): Boolean {
// Inflate the menu; this adds items to the action bar if it is present.
menuInflater.inflate(R.menu.main, menu)
diff --git a/app/src/main/java/com/lhw/pdf/MyPresentation.kt b/app/src/main/java/com/lhw/pdf/MyPresentation.kt
new file mode 100644
index 0000000..6499a85
--- /dev/null
+++ b/app/src/main/java/com/lhw/pdf/MyPresentation.kt
@@ -0,0 +1,50 @@
+package com.lhw.pdf
+
+import android.app.Presentation
+import android.content.Context
+import android.graphics.Bitmap
+import android.util.DisplayMetrics
+import android.view.Display
+import android.view.WindowManager
+import android.widget.HorizontalScrollView
+import android.widget.ImageView
+import android.widget.LinearLayout
+import androidx.core.view.WindowCompat
+import androidx.core.view.WindowInsetsCompat
+
+class MyPresentation(outerContext: Context, display: Display) : Presentation(outerContext, display) {
+ val displayMetrics = DisplayMetrics()
+ private val layout = LinearLayout(this.context)
+ private val scroll = HorizontalScrollView(this.context)
+ private val layoutParams = WindowManager.LayoutParams()
+ init {
+ @Suppress("DEPRECATION")
+ display.getMetrics(displayMetrics)
+ window?.let {
+ WindowCompat.getInsetsController(it, it.decorView)
+ .hide(WindowInsetsCompat.Type.systemBars())
+ }
+ scroll.addView(layout)
+ println(layoutParams)
+ addContentView(scroll, layoutParams)
+ }
+
+ fun updateImages(bitmaps: Iterable) {
+ println("Updating presentation images")
+ println("Layout has scale ${layout.scaleX} ${layout.scaleY}")
+ layout.removeAllViewsInLayout()
+ bitmaps.forEach {
+ val img = ImageView(this.context)
+ img.setImageBitmap(it)
+ layout.addView(img)
+ img.minimumWidth = it.width // No idea what broke when I refactored this class
+ img.minimumHeight = it.height
+ println("${it.width}x${it.height}")
+ }
+ println("Presentation heights ${scroll.height} ${layout.height}")
+ }
+
+ fun setScrollProgress(progress: Float) {
+ scroll.scrollTo((progress * (layout.width - scroll.width)).toInt(), 0)
+ }
+}