Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Android 13 #15

Closed
MingTsv opened this issue May 27, 2023 · 45 comments
Closed

Android 13 #15

MingTsv opened this issue May 27, 2023 · 45 comments

Comments

@MingTsv
Copy link

MingTsv commented May 27, 2023

it doesn't work on android 13

@finepointcgi
Copy link

finepointcgi commented May 27, 2023

I just tested this on android 13 with a google pixel 5 it seems to work for me.
What error are you getting?

Edit: It does seem to be broken it looks like godot is not requesting the android.permission.READ_EXTERNAL_STORAGE which seems to be a godot bug.

@MingTsv
Copy link
Author

MingTsv commented May 27, 2023

i have given READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE and MANAGE_EXTERNAL_STORAGE permission to my game but when I click the button to run getGalleyImage() it doesn't show anything. I'm using godot 3.5 and your 3.4 plugin

@Lamelynx
Copy link
Owner

For best compatibility, you need to have the same vesion on the plugin as the version on Godot.

@MingTsv
Copy link
Author

MingTsv commented May 27, 2023

I can't find my version in your plugin

@finepointcgi
Copy link

For best compatibility, you need to have the same vesion on the plugin as the version on Godot.

I pulled the 4.0.3 aab updated the api to 31 build tools are now 30 and updated kotlin to 1.6.0. I don't think its the plugin I think its Godot itself.
See:
godotengine/godot#60635

@MingTsv
Copy link
Author

MingTsv commented May 27, 2023

Để tương thích tốt nhất, bạn cần có cùng phiên bản trên plugin với phiên bản trên Godot.

Tôi đã kéo aab 4.0.3 đã cập nhật api lên 31 công cụ xây dựng hiện là 30 và cập nhật kotlin lên 1.6.0. Tôi không nghĩ đó là plugin mà tôi nghĩ đó là Godot. Xem: godotengine/godot#60635

Did you fix it yet? Please help me if you have a solution to this problem

@blurrred
Copy link

blurrred commented Jun 16, 2023

I think this is related to API changes in Android 13. Apparently android.permission.READ_EXTERNAL_STORAGE was split into multiple different permissions.
https://developer.android.com/about/versions/14/changes/partial-photo-video-access
I have tried granting my app android.permission.READ_MEDIA_IMAGES with a custom permission in Godot, but getGalleryImages() still fails to bring up the image selection interface.

@Lamelynx
Copy link
Owner

I'm looking into implentering Photo picker , it might fix the problem.

@blurrred
Copy link

blurrred commented Jul 25, 2023

I was able to implement photo picker in Android (including 13) with the following code:

	public void getGalleryImage() {
		Log.d("godot", "Call - getGalleryImage");
		Intent intent = new Intent(Intent.ACTION_PICK);
		intent.setType("image/*");
		startActivityForResult(getActivity(), intent, 101, null);
	}

	public void onMainActivityResult(int requestCode, int resultCode, Intent data) {
		if (resultCode == RESULT_OK) {
			// Get the URI of the selected media file
			Uri imageUri = data.getData();
			Bitmap bitmap;
			try {
				InputStream imageStream = getGodot().getContext().getContentResolver().openInputStream(imageUri);
				bitmap = BitmapFactory.decodeStream(imageStream);
				imageStream.close();
			} catch (FileNotFoundException e) {
				throw new RuntimeException(e);
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
			Dictionary imageDict = new Dictionary();
			ByteArrayOutputStream stream = new ByteArrayOutputStream();
			bitmap.compress(Bitmap.CompressFormat.JPEG, 90, stream);
			try {
				stream.close();
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
			imageDict.put("0", stream.toByteArray());
			emitSignal("image_request_completed", imageDict);
		}
	}

	@NonNull
	@Override
	public Set<SignalInfo> getPluginSignals() {
		Set<SignalInfo> signals = new ArraySet<>();
		signals.add(new SignalInfo("image_request_completed", Dictionary.class));
		return signals;
	}

It should work as a drop in replacement for single images. I haven't implemented multiple selection because my app does not require it.

@Lamelynx
Copy link
Owner

Thanks for sharing @blurrred :-)

@Ayomideabdulazeez
Copy link

I'm looking into implentering Photo picker , it might fix the problem.

Hello have you been able to implement it ?

@Lamelynx
Copy link
Owner

Lamelynx commented Sep 7, 2023

Unfortunately, I haven't taken the time for that yet.

@Ayomideabdulazeez
Copy link

Unfortunately, I haven't taken the time for that yet.

Okay, but would i be able to implement it myself into your plugin, i think it's the GodotGetImage.kt i need to alter right ?

@Ayomideabdulazeez
Copy link

Ayomideabdulazeez commented Sep 7, 2023

So good news, i've been able to get it working with android 13, by checking the android version, and then applying the new persmissions required, so basically if the android version is 13 we use Manifest.permission.READ_MEDIA_IMAGES else we then use the Manifest.permission.READ_EXTERNAL_STORAGECapture

@Ayomideabdulazeez
Copy link

@Lamelynx if you want i could create a pull request ?

@Lamelynx
Copy link
Owner

Lamelynx commented Sep 8, 2023

Great work and please do a pull request. I will test it in my setup.

@Ayomideabdulazeez
Copy link

Great work and please do a pull request. I will test it in my setup.

Sure, I'll do that in my free-time

@Ayomideabdulazeez
Copy link

No problem. I forgot there was another class that I had to make in order to get it to work.

I just called it 'PhotoPicker.java' and put it in the same folder as the Godot plugin.

public class PhotoPicker extends Fragment {
	public PhotoPicker() {
		// Required empty public constructor
	}

	public static PhotoPicker newInstance() {
		PhotoPicker fragment = new PhotoPicker();
		return fragment;
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		ActivityResultLauncher<PickVisualMediaRequest> pickMedia =
				registerForActivityResult(new ActivityResultContracts.PickVisualMedia(), uri -> {
					// Callback is invoked after the user selects a media item or closes the
					// photo picker.
					if (uri != null) {
						Log.d("PhotoPicker", "Selected URI: " + uri);
					} else {
						Log.d("PhotoPicker", "No media selected");
					}
				});

		pickMedia.launch(new PickVisualMediaRequest.Builder()
				.setMediaType(ActivityResultContracts.PickVisualMedia.ImageOnly.INSTANCE)
				.build());
	}

Can you please explain a bit how this can be implemented ?

@yan88a
Copy link

yan88a commented Sep 25, 2023

Hey guys
any breakthroughs here with godot 4 and android 13?

@Lamelynx
Copy link
Owner

I have not yet successfully implement PhotoPicker but done a update based on Ayomideabdulazeez solution.
I have not tested it on a Android 13 device tough.

@yan88a
Copy link

yan88a commented Sep 28, 2023

thanks @Lamelynx ! - did a quick check - looks like it works on my s21 (android 13)
i was able to make it work via @blurrred solution as well..

@yan88a
Copy link

yan88a commented Sep 28, 2023

well, was happy to see the photo gallery is opened with both versions so assumed all works fine.
however - couldnt retrieve the "image_request_completed" signal in both options via the "get image"/"get images"

probably some permissions issue i overlooked?

@Lamelynx
Copy link
Owner

Do you have android.permission.READ_MEDIA_IMAGES?

@yan88a
Copy link

yan88a commented Sep 28, 2023 via email

@yan88a
Copy link

yan88a commented Oct 2, 2023

Sorry for taking that long.
Seems that on android 13 "onMainActivityResult" is deprecated.
therefore - "image_request_completed" signal is not fired
(still couldnt get it to work)

@Lamelynx
Copy link
Owner

Lamelynx commented Oct 2, 2023

We need to revise how the plugin i handling the activity then.

I have problems to implement PhotoPicker, I got class not found error even tough I implement "androidx.activity:activity-ktx:1.8.0-rc01" in the plugin. Everything is compiling but don't run on the device.
Can you run this code, (I just got NoClassError for class isPhotoPickerAvailable()):

if (godot.context?.let { isPhotoPickerAvailable(it) } == true) { Log.d(TAG, "PhotoPicker is available on this device") }

@yan88a
Copy link

yan88a commented Oct 2, 2023

sure thing
i implemented the"androidx.activity:activity:1.7.2"
photo picker works ok and opens on android prior to 13 - went with @blurrred implementation..
debug'd it a bit more - and the signal is not shooting - even though "onMainActivityResult" is called.
looks like the resultCode returns as "0"

still trying to figure out what that means

@yan88a
Copy link

yan88a commented Oct 4, 2023

@Lamelynx - same for me.
couldnt find the class for -
Boolean isAvilble = .isPhotoPickerAvailable(getGodot().getContext());

wired..

@yan88a
Copy link

yan88a commented Oct 4, 2023

@Lamelynx got it to work on android 13 and lower (11)
went with @blurrred solution and changed the intent action from "get image" to "action get content)
`public void getGalleryImage() {
PhotoPicker PhotoPicker = new PhotoPicker();
Log.d("godot", "Call - getGalleryImage");
//Intent intent = new Intent(Intent.ACTION_PICK);
Intent intent = new Intent();
intent.setAction(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
//activityResultLauncher.launch(intent);
startActivityForResult(getActivity(), intent, 101, null);

}

@Override
public void onMainActivityResult(int requestCode, int resultCode, Intent data) {
    Log.d("godot","result is "+ resultCode);
    if (resultCode == RESULT_OK) {
        // Get the URI of the selected media file
        Uri imageUri = data.getData();
        Bitmap bitmap;
        try {
            InputStream imageStream = getGodot().getContext().getContentResolver().openInputStream(imageUri);
            bitmap = BitmapFactory.decodeStream(imageStream);
            imageStream.close();
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        Dictionary imageDict = new Dictionary();
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, 90, stream);
        try {
            stream.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        imageDict.put("0", stream.toByteArray());
        Log.d("godot","fired signal");
        emitSignal("image_request_completed", imageDict);
    }
}`

painful.

@bouncymarble
Copy link

Hi @yan88a @Ayomideabdulazeez @blurrred , could you guys please share an .aar file that works in godot 3.5.3? I've tried to generate it myself with the solutions you provided but always get a gradle error. I'd really appreciate it, thanks.

@yan88a
Copy link

yan88a commented Oct 5, 2023

sure @bouncymarble
aarForImage.zip

note that i only checked it with godot 4.1.1

@Ayomideabdulazeez
Copy link

Hi @yan88a @Ayomideabdulazeez @blurrred , could you guys please share an .aar file that works in godot 3.5.3? I've tried to generate it myself with the solutions you provided but always get a gradle error. I'd really appreciate it, thanks.

Hello, what error do you receive?

@bouncymarble
Copy link

Thank you @yan88a , unfortunately I was only able to export the app, had to increase Min SDK to 24 to fix a build error, but the plugin won't load while debugging.

@Ayomideabdulazeez

Hello, what error do you receive?

"Module was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.7.1, expected version is 1.1.16.". I fixed that one but then, "Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.". Same error with other gradle versions, so idk what I'm doing wrong.

@yan88a
Copy link

yan88a commented Oct 5, 2023

@bouncymarble - try it with this gdap.
note that it only has 1 function -->
getGalleryImage()
you should get a dic with the selected img on signal "image_request_completed"
Image.zip

@bouncymarble
Copy link

bouncymarble commented Oct 5, 2023

@yan88a Thank you, it loaded and getGalleryImage() now opens the gallery, but when I pick an image it doesn't return anything. I connected the signal "image_request_completed" but it's not triggering, cmd prints this:

Call - getGalleryImage
result is -1
fired signal

Btw, shouldn't you rename the plugin? maybe it's overriding the godot class with the same name "Image", and might be causing the error "Invalid call. Nonexistent function 'new' in base 'JNISingleton'", just another theory because now I get this error "Invalid call. Nonexistent function 'setOptions' in base 'JNISingleton'." which makes sense in this case. So maybe if you rename it to "GodotGetImage" it'll fix the Image.new() issue.

Is there a way to set the image parameters like we used to with setOptions()? I need to set image_height, image_width, keep_aspect, image_quality and image_format to avoid memory issues and unsupported image extensions.

@yan88a
Copy link

yan88a commented Oct 5, 2023

well,
it wont have any abilities to set anything :)
just added the getimage function (that was my needed functionality)
in my case- with godot 4.1.2 it does return a dict (by the way - the intent result code is -1 --> like in your case)

as for the nonexistant function - in your case - its really not implemented in the plugin..

in mine - i do think its an issue with the gradle config, will play with it.. if by some miracle i'll manage to make it work - i'll share the aar & gdip here...

@yan88a
Copy link

yan88a commented Oct 5, 2023

@bouncymarble - you are a wizard.
it was the name confusing it..
in any case - here is the aar & its gdap
Picker.zip
basically it only has 1 function and 1 signal:
getGalleryImage()

image_request_completed - note that it return's a dictionary with 1 key (the pic..)

thanks man,

hope it will help you as well :)

@yan88a
Copy link

yan88a commented Oct 6, 2023

@bouncymarble - you managed to get an image and parse it in the editor?
most images return in an array (some return as null)

@bouncymarble
Copy link

@yan88a I confirmed your plugin is incompatible with godot 3.5.3 because the way of connecting signals changed in godot 4. picker.connect("image_request_completed", self, "_on_image_request_completed") doesn't work, it has to be picker.image_request_completed.connect(_on_image_request_completed). I just did a test in godot 4.1.2 and it returns the dictionary as expected. So I guess I'll keep struggling with android studio. Thanks for your help anyway :)

@yan88a
Copy link

yan88a commented Oct 6, 2023 via email

@bouncymarble
Copy link

@yan88a Yeah I'm trying to export it with the library "godot-lib.3.5.3.stable.release.aar", but maybe you could zip your project folder (android studio), so I can adapt it to my needs, plus I really want to learn how to export a plugin. Sorry for bothering you 😅

@yan88a
Copy link

yan88a commented Oct 6, 2023 via email

@yan88a
Copy link

yan88a commented Oct 6, 2023

@bouncymarble - so -
here is an exported aar with 3.5 template -
aarFile.zip
and the project zip -
picker.zip
couldnt zip it with the godot lib - place it into picker/app/libs and rename to godotLib.aar - than make sure to sync the gradle.

in any case - my masters degree in android plugins was by @finepointcgi ...
here is his youtube video on that - he really did an amazing job
https://youtu.be/kwf8SFfH4s8?si=SiTxpCxJisKAiGLp

now - if you managed to get the array into the editor from the plugin - let me know if you managed to convert it in the editor to a picture.. still having some difficulties with that.

and id anyone here has a lead on ios plugins creation - that would be an early Christmas for me :)

@djordjije
Copy link

I have been following this for a while. @yan88a congratulations on making your own!
So, is there no way to get a single image from Android with a Godot 4 template currently?
I am looking for the ability to get a single image from both Android and iOS with Godot 4.
I don't mind making my own aar file. But would that even work? I am new to Godot and sorry if I am not phrasing it properly.

@Lamelynx
Copy link
Owner

Lamelynx commented Dec 8, 2023

This issue should have been resolved.
Plugin is from now on only supported by Godot 4.2+ due to plugin architecture version 1 is deprecated.

@Lamelynx Lamelynx closed this as completed Dec 8, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants