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

Add resources #2684

Merged
merged 7 commits into from
Nov 4, 2022
Merged

Add resources #2684

merged 7 commits into from
Nov 4, 2022

Conversation

RobertFlatt
Copy link
Contributor

Why does adding Android resources have so many PRs but no implementation? Clearly users think it is a necessary feature. This is another try.

There are two outstanding PRs, #2580 and #2299. And a partial solution has previously been incorporated #2330, but is not documented in buildozer.spec and apparently doesn't work kivy/buildozer#1508.

This PR is based on the observation that there is a simple hack for adding resources using add_assets and prefixing the second field with ../res/ like this

android.add_assets = icons/all-inclusive.png:../res/drawable/all_inclusive.png

This implementation simply copies the add_assets code fragments, and changes 'asset' to 'resourse'. The associated Buildozer PR is kivy/buildozer#1513

A test case is here https://github.com/RobertFlatt/add_resourse_test , this test sets a service icon (a custom service is created because setting the icon is not standard feature - but that is another issue). A drawable resource is declared using:

android.add_resources = icons/all-inclusive.png:drawable/all_inclusive.png

And the required resource ID is obtained with:

	    iconId = getResources().getIdentifier("all_inclusive",
						  "drawable",
						  getPackageName());

The test service is sticky, the app can be stopped but the service and its icon continue. So don't forget the stop the service at some point.

@misl6 misl6 self-requested a review October 10, 2022 16:34
Copy link
Member

@misl6 misl6 left a comment

Choose a reason for hiding this comment

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

I think we need to find a definitive solution, as it's clearly something that is missing and a lot of users are also complaining about it (also some plyer PR could take advantage of resources).

Unfortunately, after some tests, I found out that this PR may need some fixes before getting merged.

  1. --add-resource=mipmap:drawable-xhdpi: drawable-xhdpi already exists into the template, so shutil.copytree fails.
  2. --add-resource=mipmap:drawable-hdpi-v4: drawable-hdpi-v4 doesn't exists into the template, but if multiple builds are done with --add-resource=mipmap:drawable-hdpi-v4, also here shutil.copytree will fail
  3. --add-resource=test.jpg:drawable/test.jpg: It works, but if on a subsequent build I remove the resource (or I change the destination), the previous one does not get removed.

For 1 & 2: Luckily the solution is quite easy 😃
3: A JSON file that stores the status + a logic that does the sweeping could be the right choice?

PS: We could implement (3) later, but we will need to open an issue to track it.

@RobertFlatt
Copy link
Contributor Author

1,2 ) These two have syntax errors, because of two :. Ref: https://github.com/RobertFlatt/buildozer/blob/add_resources/buildozer/default.spec#L190-L192

What should these cases be?

  1. Yes, but I think the real issue is also shown by 2), it shows that main/src/res is stateful - which I assume it should not be.

The issue is that the res directory gets it initial state from the sdl2 bootstrap, by including these directories files https://github.com/RobertFlatt/python-for-android/tree/add_resources/pythonforandroid/bootstraps/sdl2/build/src/main/res Subsequent changes are cumulative as the initialization does not occur for each build, hence the 'apparent' state. Thus the 'apparent' state is an artifact of the build architecture.

Since the bootstrap is completely separate, a resolution to make res stateless is a copy of the res from the fist pass. Presumably would be bootstrap independent. At the start of code where resources are added:

# of the general form:
res_dir_initial = "src/res_initial"
if exists(res_dir_initial):
    rmtree(res_dir)
    copytree(res_dir_initial, res_dir)
else:
    copytree(res_dir, res_dir_initial)

Is there a better way? (please be specific)

Subsequent copytree() would have dirs_exist_ok=True

So user options override defaults, and specific options override general options. Which seems reasonable. (to me)

  1. Enhancement:
    While this PR allows specifying files or directories as resources of a given kind, it does not allow a single specification of a directory of resources of many kinds. There is no way to specify a single directory containing drawable and xml and....

I propose changing the semantics of the zero : syntax, this would add the third case below. The current usage is trivial (an implicit drawable:drawable) and can be implemented in case 2 below. The internal implementation is to make resource_dest == "" in this case.

# (list) Put these files in the apk res directory.
# The option may be used in three ways, the value may contain one or zero ':'
# Some examples:
# 1) A file to add to resources, legal resource names contain ['a-z','0-9','_']
# android.add_resources = my_icons/all-inclusive.png:drawable/all_inclusive.png
# 2) A directory, here  'legal_icons' must contain resources of one kind
# android.add_resources = legal_icons:drawable
# 3) A directory,here 'legal_resources' must contain one or more directories, 
# each of a resource kind:  drawable, xml, etc...
# android.add_resources = legal_resources

Implemented except TODO the buildozer.spec template to the comments above.

@misl6
Copy link
Member

misl6 commented Oct 15, 2022

1,2 ) These two have syntax errors, because of two :

--add-resource=mipmap:drawable-xhdpi only have a single :, isn't that legal?

Yes, but I think the real issue is also shown by 2), it shows that main/src/res is stateful - which I assume it should not be.

Unless I'm missing something (that part of python-for-android needs some cleanup) , there's no need to be stateful, so there's absolutely no reason to be.

So user options override defaults, and specific options override general options. Which seems reasonable. (to me)

Absolutely reasonable.

I propose changing the semantics of the zero : syntax, this would add the third case below. The current usage is trivial (an implicit drawable:drawable) and can be implemented in case 2 below. The internal implementation is to make resource_dest == "" in this case.

Nice! (I'm just not sure that --add-resource is something self-explanatory in that case., and we need to document that a [case 4] + [case 1,2,3] could be used at the same time, but the order may change the final result, in case of a file that overrides another one)

Looks like we found the final solution for the resources drama, can you also take care of the python-for-android docs in this PR, in order to document this feature?

@RobertFlatt
Copy link
Contributor Author

@misl6 I think this is done, but I'm not 100% certain about our communication so let me know if I missed something.

@misl6
Copy link
Member

misl6 commented Oct 21, 2022

Hi @RobertFlatt ,
Sorry for the late reply, but I've been quite busy last week 😄

What about:

1,2 ) These two have syntax errors, because of two :

--add-resource=mipmap:drawable-xhdpi only have a single :, isn't that legal?

@RobertFlatt
Copy link
Contributor Author

Hey @misl6 , I think I figured out the communication issue, my email client (Windows Mail) does not render whatever as code highlighted. So it looked like this, hence comments about two colons
image

On the subject of communication, your test copies from a directory named mipmap but not to the mipmap resource. Is there some specific intent related to this name?

So back to actual behavior....

android.add_resources =
    res_icons/all_inclusive_48.png:drawable-xhdpi,
    mipmap:drawable-hdpi,
    res_icons/all_inclusive.xml:mipmap    

Unzips as (the local minmap directory contains the 2 pngs) :

 extracting: res/drawable-hdpi-v4/align_vertical_top.png
 extracting: res/drawable-hdpi-v4/all_inclusive.png
 extracting: res/drawable-hdpi-v4/ic_launcher.png
 extracting: res/drawable-mdpi-v4/ic_launcher.png
 extracting: res/drawable-xhdpi-v4/all_inclusive_48.png
 extracting: res/drawable-xhdpi-v4/ic_launcher.png
 extracting: res/drawable-xxhdpi-v4/ic_launcher.png
 extracting: res/drawable/presplash.jpg
  inflating: res/layout/chooser_item.xml
  inflating: res/layout/main.xml
  inflating: res/layout/project_chooser.xml
  inflating: res/layout/project_empty.xml
  inflating: res/mipmap/all_inclusive.xml
 extracting: res/mipmap/icon.png

The "-v4" is antiquated (some Gradle default?) https://developer.android.com/studio/write/image-asset-studio#notification but I assume it doesn't matter.

FYI, the 'mipmap' xml resource also worked as a notification icon. The ModernDesign icons offer xml, it is the easy way to go.

Subject to my question about mipmap in your test, I think good to go.

@misl6
Copy link
Member

misl6 commented Oct 23, 2022

On the subject of communication, your test copies from a directory named mipmap but not to the mipmap resource. Is there some specific intent related to this name?

Absolutely not. I just did not rename the source folder, as what I wanted to test here was something related to the copying mechanism, which is unrelated to the source folder name.

For clarity:

If I copy a full folder to an existing one (E.g. drawable-xhdpi, which is provided by our template) via --add-resource=myfolderwhereistoremyfiles:drawable-xhdpi that will fail when shutil.copytree is asked to do so, as the folder already exists.

@RobertFlatt
Copy link
Contributor Author

I think that was addressed 20ccb7c

As shown #2684 (comment) by

android.add_resources =
    mipmap:drawable-hdpi

Unzips as (the local minmap directory contains the 2 pngs) :

 extracting: res/drawable-hdpi-v4/align_vertical_top.png
 extracting: res/drawable-hdpi-v4/all_inclusive.png
 extracting: res/drawable-hdpi-v4/ic_launcher.png

Copy link
Member

@misl6 misl6 left a comment

Choose a reason for hiding this comment

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

LGTM. Thank you!

@misl6 misl6 merged commit 5ca3a52 into kivy:develop Nov 4, 2022
@RobertFlatt
Copy link
Contributor Author

@misl6 Thanks.
Also there is a complementary Buildozer PR kivy/buildozer#1513

shyamnathp pushed a commit to shyamnathp/python-for-android that referenced this pull request Feb 17, 2023
* add_resources

* add_resource

* Update build.py

* stateless

* multiple kinds

* pep8

* --add_resource
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

2 participants