Selaa lähdekoodia

Merge branch 'fixCopyFileInfoFactoryFilePath' into 'master'

修改CopyFileInfoFactory::getFilePathFromUri workaround

See merge request kdanandroid/pdf/pdfreaderreadermodule!43
Wayne Huang 5 vuotta sitten
vanhempi
commit
9231988cae
1 muutettua tiedostoa jossa 53 lisäystä ja 10 poistoa
  1. 53 10
      src/main/java/com/kdanmobile/reader/copyfile/CopyFileInfoFactory.kt

+ 53 - 10
src/main/java/com/kdanmobile/reader/copyfile/CopyFileInfoFactory.kt

@@ -7,7 +7,41 @@ import com.kdanmobile.reader.utils.UriToPathUtil
 import java.io.File
 import java.io.FileNotFoundException
 import java.net.URLEncoder
-import java.util.regex.Pattern
+
+/**
+ * When PDF Reader opens a file which is not in the 'KdanPDFReader' folder,
+ * the target file would be copied into that folder.
+ *
+ * In order to determine the file is in the 'KdanPDFReader' folder or not,
+ * we need to know its absolute path.
+ *
+ * If a user launches PDF Reader by a third-party application,
+ * that application would send PDF Reader a uri packaged in intent.
+ *
+ * The uri is generated by the content provider of that application,
+ * and only its content resolver knows how to resolve it.
+ *
+ * The uri may be encoded or even may look like a random string,
+ * and there is no common specification among different applications.
+ *
+ * We use the function CopyFileInfoFactory::getFilePathFromUri (actually UriToPathUtil::getPath in most case) to get absolute file path through uri.
+ *
+ * However, sometimes the UriToPathUtil::getPath function may not work well (due to the wrong implementation of content provider of third-party applications),
+ *
+ * In that case, we would try to use a workaround to fix it.
+ *
+ * The workaround: we try to find whether a file name '.../KdanPDFReader/${filename of decoded uri}' or '.../KdanPDFReader/${filename of raw uri} exists of not,
+ *                 and we consider the file as the target if the file exists.
+ *
+ * If finally the workaround still fails, we cannot get the correct file path.
+ *
+ * We always copy files when we do not know those files are in the 'KdanPDFReader' folder or not.
+ *
+ * Note: uri.path / uri.pathSegments / uri.lastPathSegment /... is automatically decoded even if the raw uri is not encoded,
+ * and it would cause some problems if the raw file path contains '%' characters.
+ *
+ * To avoid those problems, we need to additionally encode each segment of the raw uri in the above case.
+ */
 
 class CopyFileInfoFactory {
     fun createInfo(applicationContext: Context, intent: Intent, kdanPdfReaderFolder: File): CopyFileInfo {
@@ -26,17 +60,26 @@ class CopyFileInfoFactory {
         if (null == uri) return null
         var filePath = UriToPathUtil.getInstance().getPath(applicationContext, uri)
         //  workaround
-        if (filePath.isNullOrEmpty() && null != uri.path) {
-            val folderName = kdanPdfReaderFolder.name
-            val pattern = Pattern.compile("$folderName/.*\\.(([Pp][Dd][Ff])|([Ee][Pp][Uu][Bb]))")
-            val matcher = pattern.matcher(uri.path)
-            if (matcher.find()) {
-                val path = "${kdanPdfReaderFolder.absolutePath}/${matcher.group().substring(folderName.length)}"
-                val file = File(path)
-                if (file.exists()) {
-                    filePath = file.absolutePath
+        if (filePath.isNullOrEmpty()) {
+            val folderName = if (kdanPdfReaderFolder.name.last() == File.separatorChar) kdanPdfReaderFolder.name else (kdanPdfReaderFolder.name + File.separatorChar)
+
+            fun fixFilePath(path: String) {
+                val index = path.indexOf(folderName)
+                if (index != -1) {
+                    val filename = path.substring(index + folderName.length)
+                    val file = File("${kdanPdfReaderFolder.absolutePath}/$filename")
+                    if (file.exists()) {
+                        filePath = file.absolutePath
+                    }
                 }
             }
+
+            uri.path?.also {
+                fixFilePath(it)
+            }
+            if (null == filePath) {
+                fixFilePath(uri.toString())
+            }
         }
         if (null != filePath && !File(filePath).exists()) {
             filePath = Uri.decode(filePath)