I have just retried and I have successfully opened a file by forcing the android sdk version to 20. However this only works through APDE as there is no way to change it in the windows version.
I also came across some code
one to stream file to a bitmap. Which by my understanding isnt ideal because it requires a possible file duplication. I’m not sure whether the PImage then makes a symbolic link to the original bitmap or whether it has to convert it somehow.
The second part is supposed to check for permissions, as the code above fails, with the following error;
open failed: EACCES (Permission denied) android
import android.net.Uri;
import android.database.Cursor;
import android.content.Intent;
import android.provider.MediaStore;
import android.app.Activity;
import android.content.Context;
import android.os.Environment;
import android.Manifest;
//import android.appcompat.app.AppCompatActivity;
import java.io.*;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.io.FileInputStream;
import java.awt.FlowLayout;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import android.graphics.*;
private static final int REQUEST_EXTERNAL_STORAGE = 1;
Activity act;
Context mC;
PImage img;
boolean img_loaded;
String s;
void settings() {
fullScreen();
}
void setup() {
//verifyStoragePermissions();
s = Environment.getExternalStorageDirectory().getAbsolutePath();
println(s);
background(#F9C454);
fill(#4A3A16);
textSize(38);
textAlign(CENTER);
text("Click on screen", width/2, height/3);
act = this.getActivity();
mC= act.getApplicationContext();
}
void draw() {
if (img_loaded&&img!=null) image(img, 0, 0);
}
void mousePressed() {
searchImage();
}
public void searchImage() {
Intent intent = new Intent(Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
intent.setType("image/*");
//Activity a =
act.startActivityForResult(intent, 1);
}
@Override
void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1) {
if (resultCode == Activity.RESULT_OK) {
if (data != null) {
Uri selectedImage = data.getData();
String[] filePathColumn = { MediaStore.Images.Media.DATA };
Cursor cursor = mC.getContentResolver().query(selectedImage,
filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String imgDecodableString = cursor.getString(columnIndex);
cursor.close();
println( imgDecodableString);
img = loadImage( imgDecodableString);
img_loaded = true;
} else {
println("Cancelled");
}
}
}
}
//new PImage function;
@Override
public PImage loadImage(String filename) { //, Object params) {
// return loadImage(filename, null);
println("Processing CUSTOM loading image....",filename);
File imgFile = new File(filename);
InputStream stream=null;
try {
//stream = surface.getAssets().open(filename); //new FileInputStream(filename);//createInput(filename);
stream = new FileInputStream(imgFile);
}
//catch(FileNotFoundException e) {}
catch(IOException e) {
e.printStackTrace();
}
if (stream == null) {
System.err.println("Could not find the image " + filename + ".");
return null;
}
// long t = System.currentTimeMillis();
Bitmap bitmap = null;
try {
bitmap = BitmapFactory.decodeStream(stream);
}
finally {
try {
stream.close();
stream = null;
}
catch (IOException e) {
}
}
// int much = (int) (System.currentTimeMillis() - t);
// println("loadImage(" + filename + ") was " + nfc(much));
if (bitmap == null) {
System.err.println("Could not load the image because the bitmap was empty.");
return null;
} else {
PImage image = new PImage(bitmap);
image.parent = this;
return image;
}
}
//--------------------------------------------------------------------------------------------------------------------
permission checking code
//--------------------------------------------------------------------------------------------------------------------
private static String[] PERMISSIONS_STORAGE = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
};
/**
* Checks if the app has permission to write to device storage
*
* If the app does not has permission then the user will be prompted to grant permissions
*
* @param activity
*/
public static void verifyStoragePermissions(Activity activity) {
// Check if we have write permission
int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (permission != PackageManager.PERMISSION_GRANTED) {
// We don't have permission so prompt the user
ActivityCompat.requestPermissions(
activity,
PERMISSIONS_STORAGE,
REQUEST_EXTERNAL_STORAGE
);
}
};
Please note the sketch wont run if the permission checking code isn’t commented out. Looking online I found that code as a solution on stackoverflow, but have absolutely no idea what to do with it…
I shall see if downgrading android studio to an older sdk would be a solution. This clearly wont be acceptable for everyone but, for people who just want to get there sketches running on their android devices quickly it could be a solution.
I also attempted to add the following line in the xml in the application tag.
android:requestLegacyExternalStorage="true"
however this results in a build failure too.
glad I’m not the only one who struggled finding a solution. And coming from processing as a 2nd language I can say that android documentation is extremely frustrating.
after further testing the maximum target sdk that can currently be used is 22. 22 and below will prompt user for permissions to stored media, anything after does not ask for user permissions.
Ok so have tried all afternoon to try and link processing to a lower version of the api however this is a no go. I can remove apis for android studio, but processing doesn’t recognize anything below android 9 api.