Skip to content
New issue

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

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

Already on GitHub? # to your account

[Proposal] Improve workflow of extending Android classes required at runtime (e.g. Activity, Application, etc.) #465

Closed
slavchev opened this issue May 26, 2016 · 3 comments
Milestone

Comments

@slavchev
Copy link

slavchev commented May 26, 2016

Overview

This proposal aims to develop further the previous story of extending Android classes required at build time. At present we use a project template that is located in platforms/android directory which doesn't and shouldn't contains files eligible for version control. Hence the need for this issue.

Proposal

There are lots of scenarios where it is required to extend Android classes used at build time. Often when using various SDKs, for example YouTube SDK, we have to extend third party types, like Activity, which are then used in AndroidManifest.xml. These types may contain application specific code and so they should be part of the app source code tree shown below

<proj dir>
|-app
|  |-App_Resources
|     |-Android
|       |-AndroidManifest.xml
|       |-app.gradle
|       |-...
|-node_modules
|-platforms
    |-android
       |-src
       | |-main
       |   |-assets
       |   |-java
       |   |-res
       |-...

Instead of storing the extended classes in platforms/android/src/main/java directory we can adjust the directory structure as follows

<projdir>
|-app
|  |-App_Resources
|     |-Android
|     | |-AndroidManifest.xml
|     | |-app.gradle
|     | |-main
|     |   |-assets
|     |   |-java
|     |   |-res
|     |-...
|-node_modules
|-platforms
    |-android
       |-src
       | |-main
       |   |-assets
       |   |-java
       |   |-res
       |-...

The idea is to preserve as much of the current gradle folder structure so it is familiar to the Android developers and avoid NIH syndrome. The exact location can be additionally configured through extend syntax for JavaScript programmers or through a decorator for TypeScript ones. For example

// MyActivity.ts
@JavaProxy("com.example.MyActivity")
class MyActivity extends com.google.android.youtube.player.YouTubeBaseActivity {
...
}

And the generated file will be stored in <projdir>/app/App_Resources/Android/main/com/example directory. In case when a static binding generator is used it should keep track whether the generated file is changed by the developer and prints a warning instead of overwriting the file. The usual way for doing this is to use the file last update time-stamp. It is up to the developer to resolve any potential conflicts.

As a first step we can add keep the existing NativeScriptApplication and NativeScriptActivity classes and add support for "secondary" activities (we keep NativeScriptActivity as a main one). The sole reason for this suggestion is that some changes in the tns modules are required. Please note that this step can be revisited if the aforementioned change is easy and won't require much time to implement.

Technical Details

I outlined some of the details but here is more detailed info.
The default platform specific directory (<platdir>) is <projdir>/app/App_Resources/Android/main. This can be configured through the existing settings.gradle file.

When No Static Binding Generator Is Used

  • All drawables are moved to <platdir>/res directory
  • During build <platdir> is copied to <projdir>/platforms/android/src overwriting all existing files

In this scenario the developer has full control over both the JavaScript and Java files. There is no synchronization between the source and the destination folders, it is one-way file copy. The tns CLI should provide tns clean command so it will be possible to clean <projdir>/platforms/android directory.

When Static Binding Generator Is Used

  • All drawables are moved to <platdir>/res directory
  • During build babeljs will parse all JavaScript/TypeScript files looking for extending native classes
  • The static binding generator will use this information and writes the *.java files <platdir>/java. If a file with newer time-stamp exists then a warning will be shown and the file won't be overwritten. The tns CLI will provide an option (e.g. --binding-overwrite) in order to overwrite an existing file
  • During build <platdir> is copied to <projdir>/platforms/android/src overwriting all existing files

Impact

The current proposal does not have any breaking changes.

Summary

This proposal makes it possible to create custom non-main activities or other classes required during build time. In order to provide full ull support for main activities further change in tns modules is required.

@atanasovg
Copy link
Contributor

After some thorough internal discussions, we've decided to follow the JavaScript-first approach. That is to enable such scenarios from JavaScript where/when possible. For 2.1 we made some refactoring in the core modules and their behavior is now easily controllable through custom Application/Activity extends. For more information please refer to this article:

https://github.com/NativeScript/android-runtime-docs/blob/master/advanced-topics/extend-application-activity.md

@Plamen5kov
Copy link
Contributor

It might be a good idea to follow the gradle project structure, as mentioned in the proposal, to avoid complicated logic on CLI side when copying resources. This will also help with declaring and controlling xml files, that are currently not the subject of change. Currently, because of the style.xml file we can't build with lower api level than 21. Example of these files:

everything in:
platforms/android/src/main/res/values
platforms/android/src/main/res/values-21

@atanasovg
Copy link
Contributor

Closing the issue, @Plamen5kov's comment moved as a separate issue.

# for free to join this conversation on GitHub. Already have an account? # to comment
Projects
None yet
Development

No branches or pull requests

4 participants