Quick Links: Download Gideros Studio | Gideros Documentation | Gideros community chat | DONATE
Media plugin — Gideros Forum

Media plugin

MoKaLuxMoKaLux Member
edited September 2019 in Plugins
my dear giderians, I would like to commit this to gideros github for ANDROID media plugin:
public static void savePicture(String xpath, String... xname) {
	// copy to public directory
	Bitmap source = loadBitmap(xpath);
	Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).mkdirs();
	String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
 
	// check if optional folder/file name parameter exists
	// Example xname = "myfolder/myimage_20190924_073644.png"
	String imageFileName = xname.length > 0 ? xname[0] : "gideros_" + timeStamp + ".png";
	String destination = Environment.getExternalStoragePublicDirectory(
		Environment.DIRECTORY_PICTURES).toString() + "/" + imageFileName;
 
	savePngBitmap(destination, source);
 
	// let media scanner scan it.
	// NOTE: I don't think that this works with png file format
}
In short this would allow us to:
- create a folder of our choice in SD/Pictures/ (optional) ex: "myfolder/myimage_date.png"
- choose a name for our image file (optional) ex: "myimage_date.png"
- by default the saved folder is SD/Pictures/
- by default the saved image would be "gideros_" + timeStamp + ".png"
- save as PNG 100 with this function:
private static void savePngBitmap(String path, Bitmap image){
	try {
		FileOutputStream out = new FileOutputStream(path);
		image.compress(Bitmap.CompressFormat.PNG, 100, out); // why not 100?
		out.close();
	} catch (Exception e) {
		e.printStackTrace();
	}
}
What do you think? Do you see any errors in the java code that I have posted? Thank you.
Or we can make it to save to png by default (now it saves to jpg) and not passing the image extension: "myfolder/myimage_date" but that looks weird!
PS: I don't know any ios programming!
my growING GIDEROS github repositories: https://github.com/mokalux?tab=repositories
Tagged:
+1 -1 (+3 / -0 )Share on Facebook
«1

Comments

  • I have a question:
    If I modify the gmedia.java file in:
    C:\Program Files (x86)\Gideros\All Plugins\gmedia\source\Android\src\com\giderosmobile\android\plugins\media

    and the mediabinder.cpp in:
    C:\Program Files (x86)\Gideros\All Plugins\gmedia\source\Android\jni

    Will this work when building a new apk? Is this that easy or I need to build the libgmedia.so file as well?

    Thank you for your help. Peace.
    my growING GIDEROS github repositories: https://github.com/mokalux?tab=repositories
  • hgy29hgy29 Maintainer
    Accepted Answer
    You’ll need to rebuild the .so file if the .cpp has changed

    Likes: MoKaLux

    +1 -1 (+1 / -0 )Share on Facebook
  • MoKaLuxMoKaLux Member
    edited September 2019
    hgy29 said:

    You’ll need to rebuild the .so file if the .cpp has changed

    That was that easy! I did not change the cpp file so I did not have to rebuild the so file.
    I have modified the:
    C:\Program Files (x86)\Gideros\All Plugins\gmedia\bin\Android\src\com\giderosmobile\android\plugins\media\GMedia.java
    Then I compiled the apk within gideros and that worked!!!

    The changes I have made:
    public static void savePicture(String path) {
    	// create the bitmap
    	Bitmap source = loadBitmap(path);
    	// save to public directory (SD/Pictures)
    	String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    	String picturespath = Environment.getExternalStoragePublicDirectory(
    		Environment.DIRECTORY_PICTURES).toString() + "/gideros"; // change folder name here
    	String imgname = "img_" + timeStamp + ".png"; // change image name here
    	String destination = picturespath + "/" + imgname;
    	// create directory
            File fileimg = new File(picturespath, imgname);
    	fileimg.getParentFile().mkdirs();
    	// then save to disk
    	saveBitmap(destination, source);
     
    	//let media scanner scan it
    	Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
    	File f = new File(destination);
    	Uri contentUri = Uri.fromFile(f);
    	mediaScanIntent.setData(contentUri);
    	sActivity.get().sendBroadcast(mediaScanIntent);
    }
    and
    private static void saveBitmap(String path, Bitmap image){
    	try {
    		FileOutputStream out = new FileOutputStream(path);
    		image.compress(Bitmap.CompressFormat.PNG, 100, out);
    		out.close();
    	} catch (Exception e) {
    		e.printStackTrace();
    	}
    }
    You can modify the above code to your needs (ex: change folder name, file name).
    What it does now:
    - saves the picture to folder: SD/Pictures/gideros/ (or any of your liking!)
    - the name of the file saved is now: "img_" + timeStamp + ".png" (or any of your liking!)
    - the new format is png (100)

    Next step: add the folder and file name inside gideros gmedia function. Something like this:
    mediamanager:postPicture(sourcepath, destfolder, destname)
    Those would be optional.
    my growING GIDEROS github repositories: https://github.com/mokalux?tab=repositories
  • MoKaLuxMoKaLux Member
    edited September 2019
    more progress here:
    - added SHOW ANDROID BOX ALLOW APP TO ACCESS MEDIA when saving picture to SD card (tested in gideros export apk target 26, 28 & 29!)

    GREAT SUCCESS!
    Will commit to gideros github (God's willing)

    Viva gideros!

    image.png
    380 x 840 - 105K
    my growING GIDEROS github repositories: https://github.com/mokalux?tab=repositories
    +1 -1 (+4 / -0 )Share on Facebook
  • MoKaLuxMoKaLux Member
    edited October 2019
    I have a question please:
    I am still working on the gmedia plugin to make it fully functional again. What I have so far:
    - (see post above) OK
    - asking camera permission OK
    - taking photos (so far I can only take thumbnail photos, the full photo involves much more android code and gideros dependencies, so I am a bit stuck here!) QUITE OK
    - playing VIDEOS from inside gideros assets (tested with .mp4) OK B)

    I am trying to override onRequestPermissionsResult so I have modified the gideros android template by adding the following:
    import android.support.v4.app.ActivityCompat;
    public class mediaexample04Activity extends Activity implements OnTouchListener, ActivityCompat.OnRequestPermissionsResultCallback

    So far so good but the problem is that "gideros" generates this piece of code:
    public void onRequestPermissionsResult(int requestCode,
    String permissions[], int[] grantResults) {
    }

    That is almost perfect but:
    1- I don't see the @override tag which is needed.
    2- GiderosApplication.getInstance() does not contain the onRequestPermissionsResult(...) function so I cannot write something like the onActivityResult(...) callback like the one below:

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data)
    {
    super.onActivityResult(requestCode, resultCode, data);
    GiderosApplication.getInstance().onActivityResult(requestCode, resultCode, data);
    }


    My questions:
    1- is it a bug for the non @override?
    2- how can I add GiderosApplication.getInstance().onRequestPermissionsResult(...), Is it done in c++?

    Thank you for your help! The onRequestPermissionsResult(...) is needed so the app can do stuff after the permissions are granted. I can do without it but the UX is not so good then.
    my growING GIDEROS github repositories: https://github.com/mokalux?tab=repositories
  • MoKaLuxMoKaLux Member
    edited October 2019
    let me answer my questions:
    1- for the @override it seems to be missing in the gideros android template so I will add it OK
    2- I found where the GiderosApplication is initialized, it's in: android/GiderosAndroidPlayer/app/src/main/java/com/giderosmobile/android/player/GiderosApplication.java

    So now 1 question remains:
    1- Is android/GiderosAndroidPlayer/app/src/main/java/com/giderosmobile/android/player/GiderosApplication.java SOMEWHERE in the gideros installation folder?
    I would like to add one function to it:

    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    }


    I can't find it! How can I add the above function? Build gideros from source (please no, not yet!)?

    Thank you for your help. :)

    Likes: SinisterSoft

    my growING GIDEROS github repositories: https://github.com/mokalux?tab=repositories
    +1 -1 (+1 / -0 )Share on Facebook
  • hgy29hgy29 Maintainer
    Accepted Answer
    @MoKaLux,

    1: @Override is just a hint that the method is supposed to be overriding a base class method. It makes the compiler generate errors if not base class method with this signature exists. So it is recommanded but not required.

    2: GiderosApplication.java is precompiled inside gideros.aar file in the template

    But I think you don't need to change it. Basically what you want (I guess) is to have some callback in GMedia called when onRequestPermissionResult is called on GiderosActivity. If so just add a marker (GIDEROS TAG comment) in GiderosActivity inside the onRequestXXX callback and have the .gplugin file insert code here during export. You can insert code to directly call a GMedia function.
    +1 -1 (+2 / -0 )Share on Facebook
  • MoKaLuxMoKaLux Member
    edited October 2019
    @hgy29 thank you for pointing me to a possible direction will try.
    Just one more question:
    I want to commit this piece of code so we could overide the above mentionned method:

    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
    {
    for ( Class < ? > theClass : sAvailableClasses )
    {
    executeMethod ( theClass, null, "onRequestPermissionsResult", new Class < ? > [] { java.lang.Integer.TYPE, java.lang.Object.TYPE, java.lang.Object.TYPE }, new Object [] { new Integer ( requestCode ), new Object ( permissions ), new Object ( grantResults ) });
    }
    }

    but I am not sure about how to pass String[] and int[] arrays. Is the above code correct?

    I would like to commit so we could override onRequestPermissions inside GMedia like we do with onActivityResult(...) that would be better imho.
    my growING GIDEROS github repositories: https://github.com/mokalux?tab=repositories
  • hgy29hgy29 Maintainer
    edited October 2019 Accepted Answer
    Looks like (by googling a bit) it should be:
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
    {
     for ( Class < ? > theClass : sAvailableClasses )
     {
      executeMethod ( theClass, null, "onRequestPermissionsResult", 
       new Class < ? > [] { Integer.TYPE, String[].class, int[].class }, 
       new Object [] { new Integer ( requestCode ), permissions, grantResults });
      }
    }
    Do you want me to add it to the code and try to build ?
  • hgy29hgy29 Maintainer
    Trying right now :wink:
  • MoKaLuxMoKaLux Member
    edited October 2019
    I googled it as well but couldn't find a straight answer!
    The code you wrote (I trust your java skills) should be all we need to do this call in the GiderosActivity:
    atOverride
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    	super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    	GiderosApplication.getInstance().onRequestPermissionsResult(requestCode, permissions, grantResults[]);
    }
    Then we could do all the permissions results calls from the GMedia plugin!

    But now I am trying the gmedia.gplugin way. Should tell you more soon?!
    my growING GIDEROS github repositories: https://github.com/mokalux?tab=repositories
  • hgy29hgy29 Maintainer
    Accepted Answer
    It compiles fine, and thinking of it that permission stuff could be useful to more plugins. Maybe keep that way then. I can send you an updated aar file. Contact me on Gideros slack group if you wish.

    Likes: MoKaLux

    +1 -1 (+1 / -0 )Share on Facebook
  • MoKaLuxMoKaLux Member
    edited June 2020
    @hgy29 The new .aar works as expected. I now handle the permissions responses in the gmedia plugin file :)
    Small problem Error cannot access GiderosSettings.
    import com.giderosmobile.android.GiderosSettings;
    in AndroidTemplateActivity.java.

    Only part left: I can only capture a thumbnail of a photo, not the photo itself, should investigate more...

    Likes: SinisterSoft

    my growING GIDEROS github repositories: https://github.com/mokalux?tab=repositories
    +1 -1 (+1 / -0 )Share on Facebook
  • wow guys that contribution is sweet :*

    Likes: MoKaLux

    > Newcomers roadmap: from where to start learning Gideros
    "What one programmer can do in one month, two programmers can do in two months." - Fred Brooks
    “The more you do coding stuff, the better you get at it.” - Aristotle (322 BC)
    +1 -1 (+1 / -0 )Share on Facebook
  • yes, thanks, i hope to use these media plugin updates soon.

    Likes: MoKaLux

    +1 -1 (+1 / -0 )Share on Facebook
  • ok I have just finished testing on more phones:
    samsung S2 android 4.4 WORKING!
    samsung S5 android 6.0.1 WORKING!
    samsung J6 android 9 WORKING!

    all commits are done too!

    Likes: SinisterSoft

    my growING GIDEROS github repositories: https://github.com/mokalux?tab=repositories
    +1 -1 (+1 / -0 )Share on Facebook
  • related to this topic, if i want to write to sd on android (using lfs) then how can i show the dialog to enable this permission on the device?
  • @keszegh you set the permission with the Require plugin: App needs to to write external storage (notice the double to :) )
    my growING GIDEROS github repositories: https://github.com/mokalux?tab=repositories
  • thanks @Mokalux, i will try. and on android do you know what is the path to the 'root'?
  • so to get to internal storage i can use '/sdcard/' in lfs.
    is there such an universal path for the external sdcard as well?
  • rrraptorrrraptor Member
    edited June 2020
    keszegh said:

    so to get to internal storage i can use '/sdcard/' in lfs.
    is there such an universal path for the external sdcard as well?

    There is no standard location.

    Maybe try to brute force? :D
    local function checkDirs()
    	local posibleLocations = {"sdcard0", "external_sd", "ext_sd", "external", "extSdCard", "sdcard2"}
     
    	for _,name in ipairs(posibleLocations) do 
    		local path = ("/%s/"):format(path)
    		local success, error = lfs.chdir(path)
    		if success then 
    			text:appendText("\n"..p.." .. OK")
    		else
    			text:appendText("\n"..error)
    		end
    	end
     
    	-- emulated storage?
    	if not found then 
    	local path = "/storage/"
    	if (lfs.chdir(path)) then 
    		for file in lfs.dir(path) do
    			if file ~= "." and file ~= ".." and file ~= "self" then
    				text:appendText("\n Found: /"..file.."/ .. OK")
    			end
    		end
    	end
    end
  • keszeghkeszegh Member
    edited June 2020
    @rrraptor , you think one of these should work? on my samsung tab s4 it does not it seems.

    for me "/storage" seems to list things, one of them being the external sdcard (with a stupid arbitrary name).
    but interestingly while "/storage/emulated/0" points to internal sd, i cannot list the directories in "/storage/emulated".

    my plan was to give access to "/storage/" and then the user can browse wherever he wants, but this obstructs it.
  • MoKaLuxMoKaLux Member
    edited June 2020
    @keszegh I am not sure what you are trying to do.
    MoKaLux said:

    C:\Program Files (x86)\Gideros\All Plugins\gmedia\bin\Android\src\com\giderosmobile\android\plugins\media\GMedia.java

    public static void savePicture(String path) {
    	String picturespath = Environment.getExternalStoragePublicDirectory(
    		Environment.DIRECTORY_PICTURES).toString() + "/gideros"; // change folder name here
    	String imgname = "img_" + timeStamp + ".png"; // change image name here
    }
    As mentionned above, in the gideros installation folder, you can modify the java code :)
    Now that I see it: it would have been better to save to pictures folder directly, not pictures/gideros :/

    PS: in the java code this is line 142
    keszegh said:

    my plan was to give access to "/storage/" and then the user can browse wherever he wants, but this obstructs it.

    You can let the users browse wherever he wants with getPicture:
    https://wiki.giderosmobile.com/index.php/Mediamanager:getPicture

    But not save anywhere they want but wherever you specified (please see above).
    my growING GIDEROS github repositories: https://github.com/mokalux?tab=repositories
  • @MoKaLux , let me explain myself more. so i want to make a file explorer into my app.
    i'm using lfs.dir(path) to get a list of directories and files contained in a folder.
    now the natural thing would be to use '/' or '/storage' as the initial directory and then the user can browse to wherever he wants. the issue is that while dir('/storage') lists '/storage/emulated' correctly, yet if i try to list folders inside this, then dir ('/storage/emulated') does not list anything, e.g. it does not list'/storage/emulated/0' even though this exists and is a working path to access the internal storage.

    in short, some folders seem to be invisible for lfs.dir() and i don't know why.
  • ok, if your file explorer will look for images only then gmedia:getPicture() lets you do that (on mobile and desktop).
    my growING GIDEROS github repositories: https://github.com/mokalux?tab=repositories
  • @Mokalux, thanks, but i need to look for another type of files (among others my own format for my animating app), so i needed to make a whole file explorer from scratch, in which i use the above mentioned method with lfs to list the directories and the files with the relevant format - which does not work completely as i would expect, as i detailed above.

    still i should check out "mediamanager:getPicture() -- opens windows/android file explorer", i did not know that android has a native file explorer.

  • Btw what is the way to pop up the allow sdcard permission? (I added this permission in require)
  • hgy29hgy29 Maintainer
    Try this:
    -- Request permission
    if not application:checkPermission("android.permission.WRITE_EXTERNAL_STORAGE") then
    application:requestPermission({"android.permission.WRITE_EXTERNAL_STORAGE"})
    end
Sign In or Register to comment.