Quick Links: Download Gideros Studio | Gideros Documentation | Gideros community chat | DONATE
Best way to let users share in-game content on social media? — Gideros Forum

Best way to let users share in-game content on social media?

I've been working on updating a feature in a game to allow a user to post an image of an in-game accomplishment on Facebook. I want to share an image that's slightly different from a screen shot the user might capture on their own. In my case I'd like a fishing game to show a fish image with a message along the lines of "I just caught this (size) (species) in Fly Fishing Simulator HD".

I understand the old Facebook plugin is not really functional, so I'm looking for other options. I'll save you the detailed story of the sytem I built uploading the images to a custom PHP server script and either posting links to those images on Facebook, or trying to have the server upload them to Facebook with their Graph API. The short version is that there are a lot of complications and drawbacks.

At least on Android, once the app has saved an image it can use the media plugin to save the image in the users gallery. Is there a simple way with Gideros to then have the device open that image in their gallery or whatever app is their default viewer for the file type? If I can trigger that, the user can easily share the image to social media, contacts, etc. The function mediamanager:getPicture() brings up the gallery to let the user select an image, but not actually open it in the gallery.

I also noticed that in Gideros 2025.2 the Media plugin shows up as available only for Android, but the documentation at https://wiki.giderosmobile.com/index.php/Media lists it as available for other platforms.

Does anyone have an effective way to let users share game generated images, other than just manually taking a screenshot and opening their gallery to share it from there?

Comments

  • hgy29hgy29 Maintainer
    The share plugin perhaps ? It will accept your image data as input and open a typical os-dependent share dialog.

    Likes: MoKaLux, PaulH

    +1 -1 (+2 / -0 )Share on Facebook
  • PaulHPaulH Member
    edited February 18
    I must have missed that one entirely. It sounds perfect. But I can't seem to find any details about it. It's not listed under https://wiki.giderosmobile.com/index.php/Plugins. Is there some documentation for it?
  • @PaulH I am working on it ;)
    I got it working on my android with simple text but I need to test the other available functions.

    There are also those listeners which I need to test.

    I never used it before so this may be rough around the edges :s

    Likes: PaulH

    my growING GIDEROS github repositories: https://github.com/mokalux?tab=repositories
    +1 -1 (+1 / -0 )Share on Facebook
  • That's great! I'd love to take a look at it. Do you have any sample code I could experiment with?

    Likes: MoKaLux

    +1 -1 (+1 / -0 )Share on Facebook
  • hgy29hgy29 Maintainer
    Accepted Answer
    I used this code in an old project, to share a diploma rendered to a temporary RenderTarget:
    	local b=Buffer.new("diploma.jpg")
    	rt:save("|B|diploma.jpg")
    	local bdata=b:get()
    	b=nil
    	collectgarbage()
    	print("DIPLOMA:",#bdata)
    	local ok,share=pcall(function () return require "Share" end) 
    	if ok then
    		Analytics("diploma_share")
    		share.share("image/jpeg",bdata)
    	end

    Likes: MoKaLux, PaulH

    +1 -1 (+2 / -0 )Share on Facebook
  • Thanks! I'll give it a try.
  • MoKaLuxMoKaLux Member
    edited February 18
    thanks guys, the plugin page was already written by hgy29 but not linked on Gideros plugins page.

    So I made this page visible and I am still testing see if there are new functions/Events available.

    https://wiki.gideros.rocks/index.php/Share

    Likes: PaulH

    my growING GIDEROS github repositories: https://github.com/mokalux?tab=repositories
    +1 -1 (+1 / -0 )Share on Facebook
  • MoKaLuxMoKaLux Member
    edited February 18
    PS: we may not have access to android data folder anymore starting with android 12+

    I don't know where Buffers are saved to but this may not work no more.

    I was working on the GMedia plugin and had some success moving from the data folder to the media folder. I need to go back to it :(
    my growING GIDEROS github repositories: https://github.com/mokalux?tab=repositories
  • hgy29hgy29 Maintainer
    MoKaLux said:


    I don't know where Buffers are saved

    They are not stored at all, just kept in memory. The file content itself is sent to the share plugin.

    Likes: MoKaLux, PaulH

    +1 -1 (+2 / -0 )Share on Facebook
  • I just tried it on Android via Gideros 2025.2 and it worked perfectly!

    On iOS it failed with a message on the console saying "Client not entitled". Here's the full error:

    59638328 Plugin query method called
    Received port for identifier response: <(null)> with error:Error Domain=RBSServiceErrorDomain Code=1 "Client not entitled" UserInfo={RBSEntitlement=com.apple.runningboard.process-state, NSLocalizedFailureReason=Client not entitled, RBSPermanent=false}
    elapsedCPUTimeForFrontBoard couldn't generate a task port
    Received port for identifier response: <(null)> with error:Error Domain=RBSServiceErrorDomain Code=1 "Client not entitled" UserInfo={RBSEntitlement=com.apple.runningboard.process-state, NSLocalizedFailureReason=Client not entitled, RBSPermanent=false}
    elapsedCPUTimeForFrontBoard couldn't generate a task port
    <0x1065d1e00> Gesture: System gesture gate timed out.
    Received port for identifier response: <(null)> with error:Error Domain=RBSServiceErrorDomain Code=1 "Client not entitled" UserInfo={RBSEntitlement=com.apple.runningboard.process-state, NSLocalizedFailureReason=Client not entitled, RBSPermanent=false}
    elapsedCPUTimeForFrontBoard couldn't generate a task port
    *** Terminating app due to uncaught exception 'NSGenericException', reason: 'UIPopoverPresentationController () should have a non-nil sourceView or barButtonItem set before the presentation occurs.'
    *** First throw call stack:
    (0x19849d5ec 0x195a19244 0x19b18c4b8 0x19aff7d5c 0x19af9d1c4 0x19ad2bd40 0x19ad2b894 0x19ad2b7a8 0x19ad2b4c8 0x19ad2b3d8 0x19ad28890 0x19ad28704 0x19ad2b034 0x19ad28c50 0x1984e3f3c 0x1984e3ed0 0x1984e6b30 0x1984e5d2c 0x198538274 0x1e56814c0 0x19b07a77c 0x19aca0e64 0x104128038 0x1be6f4de8)
    libc++abi: terminating due to uncaught exception of type NSException

    Likes: MoKaLux

    +1 -1 (+1 / -0 )Share on Facebook
  • hgy29hgy29 Maintainer
    Tried just now on my iPhone (iOS 18.1.1) and it worked flawlessly. Googled a bit and it seems to happen specifically when ran from Xcode (debug mode).

    Likes: MoKaLux, PaulH

    +1 -1 (+2 / -0 )Share on Facebook
  • Ah. That makes sense! Thanks so much!
  • MoKaLuxMoKaLux Member
    edited February 19
    PaulH could you share a sample code o:) (the one from hgy29 with Buffer didn't work for me :p ). I don't know if you need to call Share after a certain delay, on a button press, if you need to compile to apk or if it works on a Gideros android player, ...

    Likes: PaulH

    my growING GIDEROS github repositories: https://github.com/mokalux?tab=repositories
    +1 -1 (+1 / -0 )Share on Facebook
  • What I'm using is only slightly modified from hgy29's. I'm using a RenderTarget created elsewhere in the code, using a buffer the same way, using different built-in analytics to see what's going on if things fail, and I added another pcall() for protection around the call to share():
    	local b=Buffer.new("fish.jpg")
    	local rt = global_share_rt
    	rt:save("|B|fish.jpg")
    	local bdata=b:get()
    	b=nil
    	collectgarbage()
    	local ok,share=pcall(function () return require "Share" end) 
    	if ok then
    		add_to_debug_log("SPIOK")
    		local ok, share = pcall(
    			function()
    				add_to_debug_log("SH.SH")
    				share.share("image/jpeg",bdata)
    			end
    		)
    	else
    		add_to_debug_log("NoSPI")
    	end

    Likes: MoKaLux

    +1 -1 (+1 / -0 )Share on Facebook
  • It's still crashing when I try it on an iPad, but the app was installed directly from Xcode, and may still be trying to communicate with Xcode, so I'm hoping that's still the reason it's not working there. I've got a new release pending with Apple, so we'll see. I also made the presence of the "share" buttons in the app dependent on a server that delivers app settings. That way if it crashes for users I can change the settings on the server to remove the "share" button for iOS users, to prevent more of those crashes until I can solve it.

    Likes: MoKaLux

    +1 -1 (+1 / -0 )Share on Facebook
  • Apple approved the update, and the image sharing works fine on iOS now.

    Likes: MoKaLux, pie

    +1 -1 (+2 / -0 )Share on Facebook
  • MoKaLuxMoKaLux Member
    edited February 20
    I tried this code but the shared image is all black!
    local b = Buffer.new("cat.jpg")
    local rt = RenderTarget.new(360, 480)
    rt:save("|B|cat.jpg")
     
    local bdata = b:get()
    b = nil
    collectgarbage()
     
    local ok, share = pcall(function() return require "Share" end)
    if ok then
    --	add_to_debug_log("SPIOK")
    	local ok, share = pcall(function()
    --		add_to_debug_log("SH.SH")
    		share.share("image/jpeg", bdata)
    	end)
    else
    --	add_to_debug_log("NoSPI")
    end
    Tried both Gideros Player and exported apk.

    I also found out that if your image is in a folder you need to do:
    local b = Buffer.new("gfx/button01.png")
    local rt = RenderTarget.new(128, 48)
    rt:save("|B|gfx/button01.png") -- add folder here too!
    local bdata = b:get()
    ...
    my growING GIDEROS github repositories: https://github.com/mokalux?tab=repositories
  • I think what's missing is populating the RenderTarget. In my case I already had the image I want to share in a RenderTarget called global_share_rt.
  • If think if you replace the line where you create rt in your code above with this, to load the texture from cat.jpg, make the RenderTarget and draw the cat image on it, that should work:
    local t = Texture.new("cat.jpg")
    local rt = RenderTarget.new(t:getWidth(), t:getHeight())
    local b = Bitmap.new(t)
    rt:draw(b)

    Likes: MoKaLux

    +1 -1 (+1 / -0 )Share on Facebook
  • MoKaLuxMoKaLux Member
    edited February 20
    Perfect so this works:
    local share = require "Share"
     
    local tex = Texture.new("gfx/cat.jpg")
    local bmp = Bitmap.new(tex)
    local rt = RenderTarget.new(tex:getWidth(), tex:getHeight())
    rt:draw(bmp)
    local buff = Buffer.new("cat.jpg")
    rt:save("|B|cat.jpg")
     
    local bdata = buff:get()
     
    share.share("image/jpeg", bdata)
    Thank you PaulH and hgy29 :)

    I can continue with the import share and getCapabilities functions of Share :)

    Likes: PaulH

    my growING GIDEROS github repositories: https://github.com/mokalux?tab=repositories
    +1 -1 (+1 / -0 )Share on Facebook
  • hgy29hgy29 Maintainer
    To explain a bit more the code (since I tend to forget I use rarely used features):
    - Buffer is used here in lieu of a temporary file: this saves physical file I/O and file allocation and thus is faster. We still need to give a name to the buffer to distinguish it from others when used in file operations through |B|, and also since RenderTarget:save() uses the file name extension to figure out in which format to save the image.
    - We could have saved it in ".png" format too, in which case the MIME type in the share() call would have been "image/png"
    - You can share a stock file directly by loading it with io.open() / file:read("*all"), without the need for a RenderTarget or Buffer.

    Likes: MoKaLux

    +1 -1 (+1 / -0 )Share on Facebook
  • thank you for the information, I will try to add some more examples to the wiki asap.

    On the other hand I was trying to add the other functions, listeners but no luck so far :s
    --print(share.getCapabilities())
     
    --share:import()
    --print(share:import()) -- false
     
    --print(share:export("image/jpeg", bdata))
    --print(share:export("gfx/cat.jpg"))
     
    -- listeners
    --share:addEventListener(Event.SHARE_IMPORT_RESULT, function(e)
    --share:addEventListener(Event.IMPORT_RESULT, function(e)
    --	print(e)
    --end)
     
    --share:addEventListener(Share.SHARE_EXPORT_RESULT, function(e)
    --share:addEventListener(Share.EXPORT_RESULT, function(e)
    --	print(e)
    --end)
    I leave it for another day :p

    Sorry!
    my growING GIDEROS github repositories: https://github.com/mokalux?tab=repositories
  • hgy29hgy29 Maintainer
    For share:import:
    local ok,sharePlugin=pcall(function () return require "Share" end) 
    local share=Share.new()
    local function decodeFileData(e)
    	print("share:import callback:",e and e.status,e and e.mime,e and e.name)
    	if e and e.status and e.status>0 then
    		print("Got Data:",#e.data)
    	else
    		print("Import failed")
    	end
    	share:removeEventListener(Event.SHARE_IMPORT_RESULT,decodeFileData)
    end
    share:addEventListener(Event.SHARE_IMPORT_RESULT,decodeFileData)
    share:import("*/*" ,"jpg") -- MIME type, extension

    Likes: MoKaLux

    +1 -1 (+1 / -0 )Share on Facebook
  • hgy29hgy29 Maintainer
    For export:
    share:addEventListener(Event.SHARE_EXPORT_RESULT,
    function (e)
    	print("share:export callback:",e and e.status)	
    end)
    share:export("Hello world!","text/plain" ,"hello.txt") -- MIME type, extension

    Likes: MoKaLux

    +1 -1 (+1 / -0 )Share on Facebook
  • MoKaLuxMoKaLux Member
    edited February 20
    Thank you you saved me o:)

    Hopefully its wiki looks good :) https://wiki.gideros.rocks/index.php/Share

    PS: with import and export you can use more than text and image. I tested with a wav file and that worked :o

    Viva Gideros <3
    my growING GIDEROS github repositories: https://github.com/mokalux?tab=repositories
Sign In or Register to comment.