Compile error with byte[]

I tried to modify path here

String defineDir(String path){
if(path.substring(0,2)=="//"){
return "file:///storage/emulated/0/AppInventor/assets/"+path.substring(3,path.length());
}else{
if(path.substring(0,1)=="/"){
return "file:///mnt/sdcard"+path;
}else {
if (path.substring(0, 7) == "file:///" {
return path;
}
else return path;
}
}
}

but it can't compare substring with "/" or "//" I don't know why !

copy from one of my extensions, hope it helps

public InputStream openFile(String filename) throws IOException {
	InputStream inputStream = null;
	if (filename.startsWith("//")) {
		filename = filename.substring(2);
		if (isReplForm) {
			inputStream = new FileInputStream("/mnt/sdcard/AppInventor/assets/" + filename);
		} else {
			final AssetManager am = activity.getAssets();
			inputStream = am.open(filename);
		}
	} else if (filename.toLowerCase().startsWith("/sdcard/")) {
		filename = "/mnt/sdcard/" + filename.substring(8);
		inputStream = new FileInputStream(filename);
	} else {
		inputStream = new FileInputStream(filename);
	}
	return inputStream;
}

Thanks very much Kevinkun.
I just have some trouble when i copy your code:

  • What is "isReplForm" variable ?
    -it ask me for "activity" variable !

but i use .startWith until subString as in your code and it works well.

so, i update my first post

ReplForm - means that it's being run in the Companion

if (form instanceof ReplForm) { // Note: form is defined in our superclass
isReplForm = true;
}

Hi, you can return the image (byte[]) as an Object and pass it to my Extension :https://ullisroboterseite.de/android-AI2-utils-en.html#img. The extension displays it on an AI2 Image Block. So you don't have to store it and worry about wasting memory. You will find my e-mail address on my page if there are further questions.

Ulli

Thanks Ulli,
It seems to be a good way, but how do i return my image as an object ?

i code in Mp3Tags:

@SimpleFunction(description = "return file's album art")
public Object album_art(String song){
File file=new File(song);
AlbumArt art;
art = new AlbumArt() ;
art.album_art(song);
return art;
}

and a new class AlbumArt

package jml.AlbumArt;
import java.io.File;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.MediaMetadataRetriever;
public class AlbumArt {
MediaMetadataRetriever metaRetriever;
byte[] image =null;
public void AlbumArt(){
}
public void album_art(String song){
File file=new File(song);
byte[] art = new byte[0];
metaRetriever = new MediaMetadataRetriever();
if (file.exists()) {
metaRetriever.setDataSource(song);
try {
art = metaRetriever.getEmbeddedPicture();
Bitmap songImage = BitmapFactory
.decodeByteArray(art, 0, art.length);
} catch (Exception e) {
}
}else {
song="file not found";
}
image=art;
}
}

I save both Mp3Tags.java and AlbumArt.java in scr/jml/
but i have compil error :

[javac] C:\Users\Jml\appinventor-sources\appinventor\components\src\jml\Mp3Tags.java:156: error: cannot find symbol
[javac] AlbumArt art;
[javac] ^
[javac] symbol: class AlbumArt
[javac] location: class Mp3Tags
[javac] C:\Users\Jml\appinventor-sources\appinventor\components\src\jml\Mp3Tags.java:157: error: cannot find symbol
[javac] art = new AlbumArt() ;
[javac] ^
[javac] symbol: class AlbumArt
[javac] location: class Mp3Tags
[javac] Note: Some input files use or override a deprecated API.
[javac] Note: Recompile with -Xlint:deprecation for details.
[javac] Note: Some input files use unchecked or unsafe operations.
[javac] Note: Recompile with -Xlint:unchecked for details.
[javac] 2 errors

You can return Object, which will just be treated as an opaque thing by the blocks language. The user won't be able to do anything to manipulate it, but it can be passed to other methods. In this case though, you probably want to write the album art data to a file somewhere and return the path so that it can be assigned to a Button's Image property or the Image's Picture property.

I tried this ewpatton, but i didn't succed to write the album art in a file: all exemples i have seen to do that use "FileOutputStream" but as soon as i use it in my code, AI compiler return an error...so i don't know how save my bitmap in a file !

What was the error? Did you forget to import FileOutputStream? You may want to look at code such as Canvas's SaveAs function, which writes the Canvas image to a file. It's definitely feasible to write to a file from an extension.

Here the code which I use in my PkgUtils extension to get application's icon:

public String Icon(String packageName) {
    try {
        FileOutputStream fileOutputStream = null;
        File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
        String ID = AppName(packageName);
        File file = new File(path, ID + ".png");
        fileOutputStream = new FileOutputStream(file);
        Bitmap img = getBitmap(packageName);
        img.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream);
        fileOutputStream.flush();
        fileOutputStream.close();
        return String.valueOf(file);
    } catch (Exception e) {
        return String.valueOf(e);
    }
}

public Bitmap getBitmap(String packageName){
    Bitmap img = null;
    try {
        Drawable icon = context.getPackageManager().getApplicationIcon(packageName);
        BitmapDrawable bitmapDrawable = (BitmapDrawable) icon;
        img = bitmapDrawable.getBitmap();
    }catch (Exception e){
        e.printStackTrace();
    }
    return img;
}

Oh thanks very much vknow36 with your code i did lots of progress:
it work fine and i succed to obtain album art by saving it in a file, passing path to extention and see it in a layout !

the only problem still existing is that it works well throug companion but as soon as i built APK it doesn't work any more...

it catch an exeption here:

file = new File("/storage/emulated/0/jmlSongImage.png");
try {
FileOutputStream outputStream = null;
try {
outputStream = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
reponse=path;
} catch (Exception e) {
e.printStackTrace();
reponse="erreur";
}

the problem is due to outputStream = new FileOutputStream(file);
even if i delete bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
I have "erreur" in reponse ...

i'm sure it's just a detail, because it works very well with companion !

The problem is that you're saving it to an absolute path on the emulated (external) storage. If the compiled app doesn't have the WRITE_EXTERNAL_STORAGE permission and request it at runtime prior to writing the file, the app will fail. Instead, you could write it to a relative file, which writes it to the app-private data directory, and then return the relative path for use in the Image or arrangement components.

Yes i thought it was something like that...
but i don't really know how define a relative path !!!
could you give me the code for it ?

It should just be a matter of not including any "/" in the filename, e.g.,

try {
  FileOutputStream out = new FileOutputStream("temp.png");
  ...
} catch (IOException e) {
  ...
}

ok. i tried it right now...

no it doesn't work ...
and it does'nt work with companion any more...

What if you try something like:

try {
  String filename = form.getCacheDir().getAbsolutePath() + "/temp.png";
  FileOutputStream out = new FileOutputStream(filename);
} catch (IOException e) {
  ...
}

it seems there is no error any more, because my code returns :
"/data/user/0/edu.mit.appinventor.aicompanion3/cache/temp.png" with companion
or "/data/user/0/appinventor.ai_jm_latour.imagesMp3/cache/temp.png" with built

but i don't really know if temp.png exists, because i can't go there and see it with my file explorer, and i can't use it in AI with blocks to display image file:



I also try to get it with "temp.png", "/temp.png", "//temp.png" but none of them display image file...

It should work with the whole absolute path. As an alternative so you can inspect the file, you could use form.getExternalCacheDir(), which will dump the file into /storage/emulated/0/Android/.../cache rather than putting it in the private directory.

YEEES !

here it is !

I don't know why other solutions doesn't work but this one do...
thank yo very much ewpatton it would be impossible to succed without your help !