2
votes

So my manager seems to think that converting an app from 2 fully native iOS and Android apps, to one cross-platform angular/nativecript app is a straightforward task (it sounds like a terrible idea to me). Im trying to research the effort required to do this. Ive created a helloworld nativescript app and im trying to see what the best way of integrating existing native code into a nativescript app is (basically i want to have access to my native webservice functions). My knowledge on this subject is severely limited.

Ive seen there is a way to make your own native packages that can be used, but this seems like it would be way to much effort and cumbersome/messy. Is there no way to just access a custom native java object inside nativescript? for example:

//Java
package com.tns;

public class TestObject {
    public String doSomething () {
        return "hello";
    }
}

//Nativescript
import { Component } from "@angular/core";

declare var com: any

@Component({
  selector: "my-app",
  template: `
    <ActionBar title="My App"></ActionBar>
    <StackLayout orientation="vertical">
            <Label [text]="message" (tap)="onTap()"></Label>
    </StackLayout>
  `
})
export class AppComponent {
    public message: string = "Hello, Angular";
    public onTap() {
        this.message = "Text Changed";
        var test = new com.tns.TestObject();
        console.log(test.doSomething());
    }
}

edit: for future readers, the above code is in fact working now

I know you can do it with just normal Android classes, but havent been able to do it with my own custom classes, maybe im just missing something though (something to do with imports maybe?).

I am getting this error when trying to run the program

app/app.component.ts(21,24): error TS2304: Cannot find name 'com'.

and I have my object just under the main folder in my project

screenshot

Basically they want us to convert certain sections of the android app to nativescript at a time while leaving all the old native functionality in tact, so that eventually the whole project will be converted to nativescript, and thus one code base for both ios and android theoretically. Sounds like a really bad way to go about it, should just start from scratch imo.

TL;DR

How to use custom java class in nativescript code?

----- Additions from comments ------

An uncaught Exception occurred on "main" thread. com.tns.NativeScriptException: Calling js method onTouch failed

[object Object] File: "file:///data/data/org.nativescript.HelloWorld/files/app/tns_modules/tns-core-modules/ui/gestures/gestures.js, line: 97, column: 40

StackTrace: Frame: function:'GesturesObserver.androidOnTouchEvent', file:'file:///data/data/org.nativescript.HelloWorld/files/app/tns_modules/tns-core-modules/ui/gestures/gestures.js', line: 97, column: 41 Frame: function:'onTouch', file:'file:///data/data/org.nativescript.HelloWorld/files/app/tns_modules/tns-core-modules/ui/core/view.js', line: 113, column: 37

at com.tns.Runtime.callJSMethodNative(Native Method)
at com.tns.Runtime.dispatchCallJSMethodNative(Runtime.java:1197)
at com.tns.Runtime.callJSMethodImpl(Runtime.java:1061)
at com.tns.Runtime.callJSMethod(Runtime.java:1047)
at com.tns.Runtime.callJSMethod(Runtime.java:1028)
...
2
If you bring the custom files into the project what you have here var test = new com.tns.TestObject() should indeed work. Does the log(test) actually output anything? As for your angular portion, is any of this going to be used on a web version? If not, I'd skip the angular piece and use plain NativeScript. There are pros/cons both ways for sure but if it's never going to be on the web, you don't gain anything with having angular in your nativescript app. Nothing that would sway me anyway :) - Brad Martin
@BradMartin Ive updated my question with some more info, im also editing my .ts file that is the main native script project folder as well, not under platforms/android/ etc FYI. Not going to be using any web component with the code, so thanks for your suggestion - Fonix
That's a TS error, nothing to do with nativescript at that point. So you have a couple options in handling the TS compiler. Set noEmitOnError:false in tsconfig.json for the project. This will allow the compiler to emit even with errors. Or you can put above the export, declare var com: any so TS knows com is just the type any There are more options in handling but that should help. TS errors are prefixed with TS so, TS2304 indicates a TS warning/error. No major road block with that :) - Brad Martin
The NativeScript team also has android and iOS typescript typings to help with intellisense and informing TS of the native classes,methods,props, etc. so the compiler doesn't bark so much. You can add those with npm install tns-platform-declarations I think. They have another tool that attempts to generate TS typings for custom java/android libraries/modules added to your project. I haven't used it though. - Brad Martin
Ok i did as you suggested by going noEmitOnError:false and declare var com: any which let it compile, but im getting a crash now, and the exception error isnt very useful, just saying to crashing in the onTouch in file gestures.js, which im assuming is related to on onTap() method ive got and crashing in there. Im going away from my computer for a bit, so ill only be able to reply in a while, but if you have any other suggestions please do leave them here, thanks a lot for this info. - Fonix

2 Answers

2
votes

Try exclude those round brackets :) Same thing to assigning classes i am using at plugin.

EDIT

It should be with those brackets :D

var test = new com.tns.TestObject();
console.log(test.doSomething());
1
votes

So as @Brad Martin explained in the comments, all you need is to declare what com is and you will be able to use the java file in your nativescript code without any hassle

//Java
package com.tns;

public class TestObject {
    public String doSomething () {
        return "hello";
    }
}

//Nativescript
import { Component } from "@angular/core";

declare var com: any //this is the important part

@Component({
  selector: "my-app",
  template: `
    <ActionBar title="My App"></ActionBar>
    <StackLayout orientation="vertical">
            <Label [text]="message" (tap)="onTap()"></Label>
    </StackLayout>
  `
})
export class AppComponent {
    public message: string = "Hello, Angular";
    public onTap() {
        this.message = "Text Changed";
        var test = new com.tns.TestObject(); //cant use this without the declare above
        console.log(test.doSomething()); //will print "hello" in the console
    }
}

Where my java file is located in the android project:

File location in Android project for reference