Compile error with byte[]

I find this to save a bipmap image in file:

	// sauve une image bipmap dans un fichier
  private File saveBitmap(Bitmap bitmap, String path) {
    File file = null;
    if (bitmap != null) {
        file = new File(path);
        try {
            FileOutputStream outputStream = null;
            try {
                //outputStream = new FileOutputStream(path); //here is set your file path where you want to save or also here you can set file object directly
                //bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream); // bitmap is your Bitmap instance, if you want to compress it you can compress reduce percentage
                // PNG is a lossless format, the compression factor (100) is ignored
            } catch (Exception e) {
                //e.printStackTrace();
            } finally {
                try {
                    if (outputStream != null) {
                        outputStream.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    return file;
}

and it doesn't compile so i tried :

// sauve une image bipmap dans un fichier
private File saveBitmap(Bitmap bitmap, String path) {
File file = null;
if (bitmap != null) {
file = new File(path);
FileOutputStream outputStream ;
}
return file;
}

but the only line:

FileOutputStream outputStream =null;

generate a GIT compil error...
so how can i save my bipmapImage in a file ?

Take a look at this:

You can't return file object either.
Just compress bitmap and return its path.

Yes vknw360, it is not a problem to compress bitmap.
the problem is to create the ".bmp" file corresponding. to do that, all codes I have found do it with "FileOutputStream outputStream" . It works well with Android studio,
but is not accepted by AI compilator and give me an error !

Ken, your link use "FileOutputStream outputStream" too so i have the same problem: error when i compil it

But why are you compressing Bitmap to bmp file.
You should compress it to png or jpeg file.
Remember you have to return path (String) not a stream or file.

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...