{"action":"created","issue":{"url":"https://api.github.com/repos/NativeScript/android-runtime/issues/283","repository_url":"https://api.github.com/repos/NativeScript/android-runtime","labels_url":"https://api.github.com/repos/NativeScript/android-runtime/issues/283/labels{/name}","comments_url":"https://api.github.com/repos/NativeScript/android-runtime/issues/283/comments","events_url":"https://api.github.com/repos/NativeScript/android-runtime/issues/283/events","html_url":"https://github.com/NativeScript/android-runtime/issues/283","id":119221398,"number":283,"title":"[Proposal] Use custom classes required at compile time (e.g. Activity, Application, etc.)","user":{"login":"slavchev","id":3962815,"avatar_url":"https://avatars.githubusercontent.com/u/3962815?v=3","gravatar_id":"","url":"https://api.github.com/users/slavchev","html_url":"https://github.com/slavchev","followers_url":"https://api.github.com/users/slavchev/followers","following_url":"https://api.github.com/users/slavchev/following{/other_user}","gists_url":"https://api.github.com/users/slavchev/gists{/gist_id}","starred_url":"https://api.github.com/users/slavchev/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/slavchev/subscriptions","organizations_url":"https://api.github.com/users/slavchev/orgs","repos_url":"https://api.github.com/users/slavchev/repos","events_url":"https://api.github.com/users/slavchev/events{/privacy}","received_events_url":"https://api.github.com/users/slavchev/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/NativeScript/android-runtime/labels/5%20-%20Done","name":"5 - Done","color":"207de5"},{"url":"https://api.github.com/repos/NativeScript/android-runtime/labels/S:High","name":"S:High","color":"eb6420"},{"url":"https://api.github.com/repos/NativeScript/android-runtime/labels/T:Feature","name":"T:Feature","color":"bfe5bf"}],"state":"closed","locked":false,"assignee":null,"milestone":{"url":"https://api.github.com/repos/NativeScript/android-runtime/milestones/12","html_url":"https://github.com/NativeScript/android-runtime/milestones/1.7.0","labels_url":"https://api.github.com/repos/NativeScript/android-runtime/milestones/12/labels","id":1588481,"number":12,"title":"1.7.0","description":"","creator":{"login":"atanasovg","id":5878999,"avatar_url":"https://avatars.githubusercontent.com/u/5878999?v=3","gravatar_id":"","url":"https://api.github.com/users/atanasovg","html_url":"https://github.com/atanasovg","followers_url":"https://api.github.com/users/atanasovg/followers","following_url":"https://api.github.com/users/atanasovg/following{/other_user}","gists_url":"https://api.github.com/users/atanasovg/gists{/gist_id}","starred_url":"https://api.github.com/users/atanasovg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/atanasovg/subscriptions","organizations_url":"https://api.github.com/users/atanasovg/orgs","repos_url":"https://api.github.com/users/atanasovg/repos","events_url":"https://api.github.com/users/atanasovg/events{/privacy}","received_events_url":"https://api.github.com/users/atanasovg/received_events","type":"User","site_admin":false},"open_issues":1,"closed_issues":9,"state":"open","created_at":"2016-02-17T14:49:01Z","updated_at":"2016-03-16T13:02:05Z","due_on":"2016-03-29T21:00:00Z","closed_at":null},"comments":30,"created_at":"2015-11-27T16:31:58Z","updated_at":"2016-03-21T21:03:25Z","closed_at":"2016-03-16T13:00:08Z","body":"## Overview\r\nIn Android development it is a standard practice to use inheritance to create custom activities, applications and other components. Currently NativeScript runtime for Android ({N}) has limited support for this scenario. This proposal aims to provide a solution for creating custom activities, applications and other components.\r\n\r\n> Note: for the sake of this proposal I use the common scenario to extend an activity class.\r\n\r\n## Current State\r\n{N} provides built-in `NativeScriptApplication` and `NativeScriptActivity` classes. While these classes helped the adoption of {N} they also provide limitations. Currently it is not possible to inherit from a third party activity or other types which are used in `AndroidManifest.xml` file.\r\n\r\n## Technical Details\r\nHere is how a Java class is extended in {N}\r\n```JavaScript\r\n// app/myactivity.js\r\nvar MyActivity = android.app.Activity.extend({\r\n   onCreate: function(bundle) {\r\n      // implementation\r\n   }\r\n});\r\n```\r\nHowever `MyActivity` class is generated at runtime by {N} bridge. This mean you cannot use `MyActivity` in `AndroidManifest.xml` the way we currently use `NativeScriptActivity` for example.\r\n```XML\r\n<!-- AndroidManifest.xml -->\r\n<activity\r\n    android:name=\"com.tns.NativeScriptActivity\"\r\n    android:label=\"TestApp\">\r\n    <intent-filter>\r\n        <action android:name=\"android.intent.action.MAIN\" />\r\n        <category android:name=\"android.intent.category.LAUNCHER\" />\r\n    </intent-filter>\r\n</activity>\r\n```\r\n\r\n## Proposal\r\nThe current `extend` implementation can accept two parameters as well. We can rewrite the previous example as follows\r\n```JavaScript\r\n// app/myactivity.js\r\nvar MyActivity = android.app.Activity.extend(\"MyActivity\", {\r\n   onCreate: function(bundle) {\r\n      // implementation\r\n   }\r\n});\r\n```\r\nWe can leverage the latter syntax of `extend` function and pass the fully qualified type name of the new class as follows\r\n```JavaScript\r\n// app/myactivity.js\r\nvar MyActivity = android.app.Activity.extend(\"com.example.MyActivity\", {\r\n   onCreate: function(bundle) {\r\n      // implementation\r\n   }\r\n});\r\n```\r\nDuring build time we can parse the JavaScript and generate Java file `com/example/MyActivity.java`. This proposal will not make the existing code ambiguous because currently there is a validation rule that says the class name cannot contain `.` symbol. The generated `MyActivity.java` file will look as follows\r\n```Java\r\n// com/example/MyActivity.java\r\npackage com.example;\r\n\r\n@com.tns.JavaScriptImplementation(javaScriptFile = \"app/myactivity.js\")\r\npublic class MyActivity extends android.app.Activity {\r\n   public MyActivity() {\r\n      com.tns.Platform.initInstance(this);\r\n   }\r\n   public void onCreate(android.os.Bundle param_0) {\r\n      Object[] args = new Object[1];\r\n      args[0] = param_0;\r\n      com.tns.Platform.callJSMethod(this, \"onCreate\", void.class, args);\r\n   }\r\n}\r\n```\r\nThis is how the currently **runtime** generated types look like. We can provide a tool that generates equivalent types at **build time**. The only difference is the use of `com.tns.JavaScriptImplementation` annotation. The need a way to find the JavaScript implementation for `MyActivity` when an instance is created. Using annotation is just one possible approach. I find it clear and, more importantly, I find it aligned with the following proposition how to extend Java class in TypeScript.\r\n```TypeScript\r\n// myactivity.ts\r\n@JavaProxy(\"com.tns.MyActivity\")\r\nclass MyActivity extends android.app.Activity {\r\n   onCreate(bundle: android.os.Bundle)  {\r\n      // implementation\r\n   }\r\n}\r\n```\r\nUsing ES6/TypeScript decorators is a simple way to indicate that we have to generate Java class at build time. The main benefit of using decorators is that the change is less obtrusive than other alternatives.\r\n\r\n## Impact\r\nThis proposal will require [{N} modules](https://github.com/NativeScript/NativeScript) to change the way an application is initialized and activities are created. I expect that this would be small-to-medium change. The immediate benefits are better encapsulation and control. Also, it may require {N} modules to come with prebuilt `Activity` and `Application` classes. Another approach would be adding these classes to the project template.\r\n\r\n## Summary\r\nThis proposal has some other benefits as well. Removing `NativeScriptActivity` and `NativeScriptApplication` from {N} will allows us to support [lower Android API levels](https://github.com/NativeScript/android-runtime/issues/198). Currently we have to compile against API level 17 and there is no technical justification for that. Also it will allow embedding {N} in other applications much easier. One primary scenario is [NativeScript companion app](https://play.google.com/store/apps/details?id=com.telerik.NativeScript&hl=en).\r\n\r\nFinally, you can find a prototype [here](https://github.com/NativeScript/android-runtime/tree/slavchev/new-project-template2)"},"comment":{"url":"https://api.github.com/repos/NativeScript/android-runtime/issues/comments/199484330","html_url":"https://github.com/NativeScript/android-runtime/issues/283#issuecomment-199484330","issue_url":"https://api.github.com/repos/NativeScript/android-runtime/issues/283","id":199484330,"user":{"login":"NathanaelA","id":850871,"avatar_url":"https://avatars.githubusercontent.com/u/850871?v=3","gravatar_id":"","url":"https://api.github.com/users/NathanaelA","html_url":"https://github.com/NathanaelA","followers_url":"https://api.github.com/users/NathanaelA/followers","following_url":"https://api.github.com/users/NathanaelA/following{/other_user}","gists_url":"https://api.github.com/users/NathanaelA/gists{/gist_id}","starred_url":"https://api.github.com/users/NathanaelA/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/NathanaelA/subscriptions","organizations_url":"https://api.github.com/users/NathanaelA/orgs","repos_url":"https://api.github.com/users/NathanaelA/repos","events_url":"https://api.github.com/users/NathanaelA/events{/privacy}","received_events_url":"https://api.github.com/users/NathanaelA/received_events","type":"User","site_admin":false},"created_at":"2016-03-21T21:03:25Z","updated_at":"2016-03-21T21:03:25Z","body":"@slavchev I **love** the idea of a JS -> Java transpiler.  I would ask that it be allowed to build a Java class from multiple JS files though.   Take for instance the permission pull I added  --  If I create a simple  NativeScriptActivty.add.js  (or some file) that the compiler would then pull the piece of code out to include in the final NSA.java file \r\nie:  \r\n```\r\nfunction OnRequestPermission(a,b) { \r\n// do something\r\n}\r\n``` \r\nand then append this inside the class.  That way individual plugins could add the needed support they might need without making the developer having to manually modify this file for these plugins.\r\n\r\nBut this could be an update; having the develop open the NativeScriptActivity.js and copy/paste the changes would be much much better than what we have now.  :grinning:\r\n\r\n "}}