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: Native Dialog Addon #1520

Merged
merged 26 commits into from
Feb 18, 2024
Merged

Conversation

alemart
Copy link
Contributor

@alemart alemart commented Dec 14, 2023

This is an implementation of the Native Dialog Addon for Android. It includes: message boxes, file chooser and text logs. Text logs are mapped to logcat. Window menus have an empty implementation.

In addition to implementing the Native Dialog Addon, I have also adapted ex_native_filechooser (please apply #1518 before testing).

Considerations about the file chooser:

  • al_show_native_file_dialog() is specified as blocking in the Allegro API. Since there is a need to handle ALLEGRO_EVENT_DISPLAY_HALT_DRAWING before that function returns, users must call it from a different thread.
  • Due to the constraints of Scoped Storage, the file chooser returns content:// URIs instead of file paths.
  • A new proposed function, al_android_open_fd(), can be used to get a file descriptor (not a file path) from a content:// URI.
    • Google has made direct file path access increasingly difficult. Even if we could reliably find the actual path of a selected file, this doesn't necessarily mean that we would have permission to access it - unless that file was located somewhere in the application storage and the system is not Android 10 (in which case a special flag is needed).
    • A common strategy to get a file path is to open a stream, copy the data to the application storage (e.g., the application cache) and return the path to the copy. This may be wasteful. I have not included any such routines in this PR.
    • Using file descriptors is a reliable way to access the data and works with native code.

Screenshots:
Screenshot_20231213-124905
Screenshot_20231212-193146

@SiegeLord
Copy link
Member

I've been following this, awesome work! How are things going?

About al_android_open_fd, why have this function as opposed to allowing al_fopen to handle this? We could use the al_set_new_file_interface to enable this as an option, or do this by default in principle.

@alemart
Copy link
Contributor Author

alemart commented Jan 5, 2024

I've been following this, awesome work! How are things going?

Thanks. I've been using it successfully. There was a bit of a challenge concerning concurrency. Allegro defines a blocking interface. This blocking interface creates the possibility of deadlocks linked to display events, which I have documented and addressed. I took extra care so that things work seamlessly.

About al_android_open_fd, why have this function as opposed to allowing al_fopen to handle this? We could use the al_set_new_file_interface to enable this as an option, or do this by default in principle.

al_android_open_fd is not opposed to al_fopen. Rather, it's a more flexible alternative to it.

This utility function returns a file descriptor, which is a well-known mechanism that also works outside of Allegro - e.g., with external libraries. In my point of view, this is the most flexible option possible, and the second best option after file paths.

Copy link
Member

@SiegeLord SiegeLord left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, it took me some time but I went through all of this. Amazing work! I just had one question, but otherwise this is good to go.


private Looper myLooper()
{
try { Looper.prepare(); } catch (Exception e) { ; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you need to discard exceptions here? Is it worth logging them?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looper.prepare() initializes the current thread as a Looper. As you can see at Looper.java, the method can throw a runtime exception that says "Only one Looper may be created per thread". The class constructor does nothing special. Would you like this logged? It doesn't seem useful and we would have this message show up repeatedly on the logs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See also: MessageQueue.nativeInit. Would you like this logged?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, that makes sense. Could you add a comment about this? Something like // Looper will raise an exception if one already exists in the thread.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure

@SiegeLord SiegeLord merged commit c4bc6dc into liballeg:master Feb 18, 2024
3 checks passed
@SiegeLord
Copy link
Member

Thanks!

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

Successfully merging this pull request may close these issues.

2 participants