0

I am writing an app which calculates the horizontal DPI of an image the user inputs. I am using the Sanselan library in Java's Common Imaging library. However, when I use the File object that is constructed from the path that is retrieved from a URI in an onActivityResult listener, passing it in as the parameter to a function that computes the horizontal DPI returns a FileNotFoundException:

onActivityResult error: java.io.FileNotFoundException: /document/image:53066 (No such file or directory)

Below is my code:

build.gradle (App):

apply plugin: 'com.android.application'

android {
    compileSdkVersion 29
    buildToolsVersion "29.0.2"
    defaultConfig {
        applicationId "com.example.changingimageviewwidth"
        minSdkVersion 26
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.3.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'

    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'

    implementation "org.apache.sanselan:sanselan:0.97-incubator"
}

activity_main.xml:

<?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="match_parent"
    android:background="#ffffff"
    android:orientation="vertical">

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button"
        android:onClick="analyzePhoto"/>

</LinearLayout>

MainActivity.java:

package com.example.changingimageviewwidth;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;

import org.apache.sanselan.ImageInfo;
import org.apache.sanselan.Sanselan;

import java.io.File;

public class MainActivity extends AppCompatActivity {
    // Request code used when reading in a file
    private Integer READ_IN_FILE = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void analyzePhoto(View v) {
        // Specify that only photos are allowed as inputs (.jpg, .png).
        Intent photoInputSpecs = new Intent(Intent.ACTION_GET_CONTENT);
        photoInputSpecs.setType("image/*");

        Intent photoInputHandler = Intent.createChooser(photoInputSpecs, "Choose a file");
        startActivityForResult(photoInputHandler, 0);
    }

    // Processes the results of Activities.
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        try {
            // Processes the photos that the user selected
            if (requestCode == READ_IN_FILE) {
                System.out.println("Let us process the photos that the user selected.");
                // Retrieve the photo's location
                Uri photoUri = data.getData();
                String photoPath = photoUri.getPath();
                File photoFile = new File(photoPath);

                ImageInfo image1Info = Sanselan.getImageInfo(photoFile);

                int image1HorizontalDPI = image1Info.getPhysicalWidthDpi();
                int image1VerticalDPI = image1Info.getPhysicalHeightDpi();

                System.out.println("[image1HorizontalDPI] = " + image1HorizontalDPI);
                System.out.println("[image1VerticalDPI] = " + image1VerticalDPI);
            }
        }
        catch (Exception ex) {
            System.out.println("onActivityResult error: " + ex.toString());
        }
    }
}
Adam Lee
  • 436
  • 1
  • 14
  • 49
  • `/document/image:53066` That is an impossible file system path. Better have a look at data.getData().toString(). – blackapps Jun 13 '21 at 07:01
  • @blackapps data.getData().toString() = "content://com.android.providers.media.documents/document/image%3A53656" – Adam Lee Jun 13 '21 at 07:11
  • Please comment on that value. – blackapps Jun 13 '21 at 07:15
  • @blackapps What do you mean by "comment on that value."? – Adam Lee Jun 13 '21 at 07:19
  • That you should say something of that value. Tell us about it. What is it? You first only took the last part and considered it to be a file system path. Now your opinion about the whole string please. Comment! – blackapps Jun 13 '21 at 07:20
  • @blackapps I'm not really sure what that value "content://com.android.providers.media.documents/document/image%3A53656" means though, other than that it is data.getData.toString(). I don't know how to get the actual file system path from it, because the value does not contain any legitimate file system path? – Adam Lee Jun 13 '21 at 07:24
  • Well that is a nice content scheme uri. And one does not try to convert a nice uri to a file path – blackapps Jun 13 '21 at 07:25
  • @blackapps So you are saying that it is impossible to get the file path from the URI, correct? – Adam Lee Jun 13 '21 at 07:27
  • No. Many times it is possible. But even if you can get a file system path your app might not have access. Any how trying to convert an uri is a bad idea as you can use the uri directly to get the file contents. – blackapps Jun 13 '21 at 07:29
  • @blackapps Thank you for the clarification :D. The main issue I guess is that the Sanselan library's getImageInfo function requires a File object as it's parameter, so I'm having trouble working around this constraint. Is there any alternate solution to get the image's horizontal DPI? – Adam Lee Jun 13 '21 at 07:30
  • I have no idea what a DPI of an image would be. I only know image resolution in pixels. What does DPI stsnd for? Does a .jpg file contain dpi info? – blackapps Jun 13 '21 at 07:31
  • @blackapps DPI means resolution number of dots per inch. – Adam Lee Jun 13 '21 at 07:34
  • @AdamLee: from what I see plenty of the APIs in that library accept either an `InputStream` or a `byte[]`. So you definitely don't need the `File`. An `InputStream` would be best, if you only want to get some info, because that could get away with reading as little information as is necessary. – Joachim Sauer Jun 13 '21 at 07:34

0 Answers0