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

Unable to run existing android app after upgrading to 1.6.0 #1577

Closed
enchev opened this issue Feb 18, 2016 · 35 comments
Closed

Unable to run existing android app after upgrading to 1.6.0 #1577

enchev opened this issue Feb 18, 2016 · 35 comments

Comments

@enchev
Copy link
Contributor

enchev commented Feb 18, 2016

From @Daxito on February 17, 2016 16:30

I just upgraded to 1.6.0 from 1.5.2 and now I get this error when trying to run the app on android, ios is ok:
Any clue? If I create a new project it works ok, seems like a problem with my existing app only, this is my exception log:

java.lang.RuntimeException: Unable to create application com.tns.NativeScriptApplication: com.tns.NativeScriptException:
Calling js method onCreate failed

Error: java.lang.RuntimeException: NativeScriptApplication already initialized
com.tns.Platform.init(Platform.java:105)
com.tns.NativeScriptApplication.onCreate(NativeScriptApplication.java:1033)
com.tns.Platform.callJSMethodNative(Native Method)
com.tns.Platform.dispatchCallJSMethodNative(Platform.java:812)
com.tns.Platform.callJSMethod(Platform.java:711)
com.tns.Platform.callJSMethod(Platform.java:690)
com.tns.Platform.callJSMethod(Platform.java:680)
com.tns.NativeScriptApplication.onCreateInternal(NativeScriptApplication.java:924)
com.tns.NativeScriptApplication.onCreate(NativeScriptApplication.java:1037)
android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1020)
android.app.ActivityThread.handleBindApplication(ActivityThread.java:5010)
android.app.ActivityThread.access$1600(ActivityThread.java:172)
android.app.ActivityThread$H.handleMessage(ActivityThread.java:1482)
android.os.Handler.dispatchMessage(Handler.java:102)
android.os.Looper.loop(Looper.java:145)
android.app.ActivityThread.main(ActivityThread.java:5835)
java.lang.reflect.Method.invoke(Native Method)
java.lang.reflect.Method.invoke(Method.java:372)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
File: ", line: 0, column: -1

StackTrace:

at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5013)
at android.app.ActivityThread.access$1600(ActivityThread.java:172)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1482)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:5835)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
Caused by: com.tns.NativeScriptException:
Calling js method onCreate failed

Error: java.lang.RuntimeException: NativeScriptApplication already initialized
com.tns.Platform.init(Platform.java:105)
com.tns.NativeScriptApplication.onCreate(NativeScriptApplication.java:1033)
com.tns.Platform.callJSMethodNative(Native Method)
com.tns.Platform.dispatchCallJSMethodNative(Platform.java:812)
com.tns.Platform.callJSMethod(Platform.java:711)
com.tns.Platform.callJSMethod(Platform.java:690)
com.tns.Platform.callJSMethod(Platform.java:680)
com.tns.NativeScriptApplication.onCreateInternal(NativeScriptApplication.java:924)
com.tns.NativeScriptApplication.onCreate(NativeScriptApplication.java:1037)
android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1020)
android.app.ActivityThread.handleBindApplication(ActivityThread.java:5010)
android.app.ActivityThread.access$1600(ActivityThread.java:172)
android.app.ActivityThread$H.handleMessage(ActivityThread.java:1482)
android.os.Handler.dispatchMessage(Handler.java:102)
android.os.Looper.loop(Looper.java:145)
android.app.ActivityThread.main(ActivityThread.java:5835)
java.lang.reflect.Method.invoke(Native Method)
java.lang.reflect.Method.invoke(Method.java:372)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
File: ", line: 0, column: -1

StackTrace:

at com.tns.Platform.callJSMethodNative(Native Method)
at com.tns.Platform.dispatchCallJSMethodNative(Platform.java:812)
at com.tns.Platform.callJSMethod(Platform.java:711)
at com.tns.Platform.callJSMethod(Platform.java:690)
at com.tns.Platform.callJSMethod(Platform.java:680)
at com.tns.NativeScriptApplication.onCreateInternal(NativeScriptApplication.java:924)
at com.tns.NativeScriptApplication.onCreate(NativeScriptApplication.java:1037)
at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1020)
at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5010)
... 9 more
Caused by: java.lang.RuntimeException: NativeScriptApplication already initialized
at com.tns.Platform.init(Platform.java:105)
at com.tns.NativeScriptApplication.onCreate(NativeScriptApplication.java:1033)
... 18 more

Copied from original issue: NativeScript/nativescript-cli#1497

@enchev
Copy link
Contributor Author

enchev commented Feb 18, 2016

From @NathanaelA on February 17, 2016 17:1

Did you upgrade BOTH the core modules, and the runtime?

@enchev
Copy link
Contributor Author

enchev commented Feb 18, 2016

From @Daxito on February 17, 2016 17:5

I followed these instructions:

https://docs.nativescript.org/releases/upgrade-instructions

npm install -g nativescript
tns platform remove android
tns platform add android
tns platform remove ios
tns platform add ios
npm install tns-core-modules@latest --save

@enchev
Copy link
Contributor Author

enchev commented Feb 18, 2016

From @NathanaelA on February 17, 2016 17:6

Yep; those are the correct instructions. I'm currently in the process of upgrading one of mine. (Slow internet right now for some reason). I'll let you know how it goes...

@enchev
Copy link
Contributor Author

enchev commented Feb 18, 2016

From @NathanaelA on February 17, 2016 17:13

Interesting, I have duplicated this issue on my own project. Investigating...

@enchev
Copy link
Contributor Author

enchev commented Feb 18, 2016

From @Daxito on February 17, 2016 17:23

I see, thanks!

@enchev
Copy link
Contributor Author

enchev commented Feb 18, 2016

From @NathanaelA on February 17, 2016 18:20

Are you loading / running any plugins inside the app.js?

@enchev
Copy link
Contributor Author

enchev commented Feb 18, 2016

From @Daxito on February 17, 2016 18:45

Yes, under the node_modules I have lodash, moment, nativescript-drop-down, nativescript-sqlite, nativescript-telerik-ui, numeral, string.

@enchev
Copy link
Contributor Author

enchev commented Feb 18, 2016

From @Daxito on February 17, 2016 18:48

oh wait, inside the app.js
a module that references
var connectivity = require("connectivity");
var dialogs = require("ui/dialogs");
var moment = require("moment");
var _ = require("lodash");
var numeral = require("numeral");

And directly under app.js:
var application = require("application");
var Everlive = require("~/lib/everlive.all.min");

@enchev
Copy link
Contributor Author

enchev commented Feb 18, 2016

From @NathanaelA on February 17, 2016 18:51

Can you post your app.js file. Your comment above left me confused. 😀

@enchev
Copy link
Contributor Author

enchev commented Feb 18, 2016

From @Daxito on February 17, 2016 18:54

here it is:

var application = require("application");
var converters = require('/converters/converters');
var connectionMonitor = require('
/service/connection-monitor');
var Everlive = require("~/lib/everlive.all.min");

application.cssFile = "./app.css";
application.mainModule = "./views/login/login";

application.resources["dateConverter"] = converters.dateConverter;
application.resources["visibilityConverter"] = converters.visibilityConverter;
application.resources["idToNameConverter"] = converters.idToNameConverter;
application.resources["timeConverter"] = converters.timeConverter;
application.resources["numberConverter"] = converters.numberConverter;

global.TOKEN_DATA_KEY = "authenticationToken";
global.USER_ITEM = "useritem";
global.SELECT_DEFAULT_TEXT = "[Select...]"
global.CONNECTION_MONITOR = connectionMonitor;
global.CONNECTION_MONITOR.startMonitoring();

// Initialize Everlive SDK
global.EVERLIVE = new Everlive(global.BS_API_KEY);

global.COMPANY_CODE = null;

application.onSuspend = function () {
console.log("Application suspended.");
};

application.onResume = function () {
console.log("Application resumed.");
};

application.onExit = function () {
console.log("Application will exit.");
};

application.onLowMemory = function () {
console.log("Memory is low.");
};

application.onUncaughtError = function (error) {
console.log("Application error: " + error.name + "; " + error.message + "; " + error.nativeError);
};

application.start();

@enchev
Copy link
Contributor Author

enchev commented Feb 18, 2016

From @Daxito on February 17, 2016 18:56

Converters content is:

var moment = require("moment");
var _ = require("lodash");
var numeral = require("numeral");

var visibilityConverter = function (value) { //To View Converter
if (value) {
return 'visible';
} else {
return 'collapsed';
}
}

var numberConverter = function (value, format) {
if (!.isNull(value)) {
format = format || "0,0.00";
if (
.isNumber(value)) {
return numeral(value).format(format);
} else {
return '';
}
} else {
return '';
}
}

var dateConverter = function (value, format) {
if (!_.isNull(value)) {
var m = moment(value);
format = format || "L";
if (m.isValid()) {
return m.format(format);
} else {
return '';
}
} else {
return '';
}
}

var timeConverter = function (value, format) {
if (!.isNull(value) && !.isUndefined(value)) {
var m = moment(value);
format = format || "LT";
if (m.isValid()) {
return m.format(format);
} else {
return '';
}
} else {
return '';
}
}

var idToNameConverter = function (value, items, defaultText) {
//We assume that the items collection contains items like {id:1,name:'foo'}
var defaultText = defaultText || '[Select...]';
if (!
.isNull(value)) {
var item = _.find(items, { id: value });
if (item) {
return item.name;
} else {
return _defaultText;
}
} else {
return _defaultText;
}
}

exports.visibilityConverter = visibilityConverter;
exports.dateConverter = dateConverter;
exports.timeConverter = timeConverter;
exports.idToNameConverter = idToNameConverter;
exports.numberConverter = numberConverter;

@enchev
Copy link
Contributor Author

enchev commented Feb 18, 2016

From @Daxito on February 17, 2016 18:57

connection-monitor content is:

var connectivity = require("connectivity");
var dialogs = require("ui/dialogs");

module.exports = (function () {
console.log('Connection Monitor Module Initialized');
var isMonitoring = false;
var connectionType = connectivity.getConnectionType(); //Get the initial value on initialization.

//Report the connection to the console for devs
switch (connectionType) {
    case connectivity.connectionType.none:
        console.log("No connection");
        break;
    case connectivity.connectionType.wifi:
        console.log("WiFi connection");
        break;
    case connectivity.connectionType.mobile:
        console.log("Mobile connection");
        break;
}

function startMonitoring() {
    console.log('Connection Monitor Enabled');
    isMonitoring = true;
    connectivity.startMonitoring(function onConnectionTypeChanged(newConnectionType) {
        if (connectionType !== newConnectionType) {
            connectionType = newConnectionType;
            var msg = '';
            switch (newConnectionType) {
                case connectivity.connectionType.none:
                    msg = "Lost Network Connection."
                    break;
                case connectivity.connectionType.wifi:
                    msg = "Connected to WiFi.";
                    break;
                case connectivity.connectionType.mobile:
                    msg = "Connected to Mobile.";
                    break;
            }

            console.log(msg);

            console.log("New connection type value" + connectionType);
            dialogs.alert(msg);
        }

    });
}


function stopMonitoring() {
    connectivity.stopMonitoring();
    isMonitoring = false;
    console.log('Connection Monitor Disabled');
}

return {
    connectionType:function(){return connectionType},
    stopMonitoring: stopMonitoring,
    startMonitoring: startMonitoring,
    isConnected: function(){
            return  (connectivity.getConnectionType() !== connectivity.connectionType.none)
        },
    isMonitoring: isMonitoring
}

})();

@enchev
Copy link
Contributor Author

enchev commented Feb 18, 2016

From @NathanaelA on February 17, 2016 19:6

Ok, I want you to try something.

It will break your app later I'm sure; but lets see if it actually runs.
Comment out:
var Everlive = require("~/lib/everlive.all.min");
and
global.EVERLIVE = new Everlive(global.BS_API_KEY);

If that doesn't work try commenting out:
var connectionMonitor = require('~/service/connection-monitor');
and
// global.CONNECTION_MONITOR = connectionMonitor;
// global.CONNECTION_MONITOR.startMonitoring();

If that doesn't work, comment out both EverLive and Connection_Monitor .

@enchev
Copy link
Contributor Author

enchev commented Feb 18, 2016

From @rosen-vladimirov on February 17, 2016 19:11

Guys, can you try removing these lines

application.cssFile = "./app.css";
application.mainModule = "./views/login/login";

and replace the start method with this one:

application.start({ moduleName: "./views/login/login" });

@enchev
Copy link
Contributor Author

enchev commented Feb 18, 2016

From @Daxito on February 17, 2016 19:13

Let me try all the recommendations right now.

@enchev
Copy link
Contributor Author

enchev commented Feb 18, 2016

From @NathanaelA on February 17, 2016 19:26

@rosen-vladimirov In my specific case switching the cssFile/MainModule to the new way didn't help. In fact I did quite a few things to my project and finally narrowed it down to the actual context access. I would not be surprised if something in his app is doing the same thing.

@enchev
Copy link
Contributor Author

enchev commented Feb 18, 2016

From @rosen-vladimirov on February 17, 2016 19:27

ok, I'll try to reproduce it on my side as well. Can you guide me for something specific. Why your app worked with 1.5.2 and not with 1.6.0

@enchev
Copy link
Contributor Author

enchev commented Feb 18, 2016

From @Daxito on February 17, 2016 19:30

OK, so this is the cause of the issue in my case, this is what gets called from the app.js when the module is "required", as you can see:

var connectivity = require("connectivity");
connectivity.getConnectionType();

@enchev
Copy link
Contributor Author

enchev commented Feb 18, 2016

From @Daxito on February 17, 2016 19:31

And this is a copy of my manifest, just in case:

<supports-screens
    android:smallScreens="true"
    android:normalScreens="true"
    android:largeScreens="true"
    android:xlargeScreens="true"/>

<uses-sdk
    android:minSdkVersion="17"
    android:targetSdkVersion="__APILEVEL__"/>

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

<application
    android:name="com.tns.NativeScriptApplication"
    android:allowBackup="true"
    android:icon="@drawable/icon"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name="com.tns.NativeScriptActivity"
        android:label="@string/title_activity_kimera"
        android:configChanges="keyboardHidden|orientation|screenSize">

            <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <activity android:name="com.tns.ErrorReportActivity"/>
</application>

@enchev
Copy link
Contributor Author

enchev commented Feb 18, 2016

From @rosen-vladimirov on February 17, 2016 19:32

This is the manifest from app/App_Resources/Android right?

@enchev
Copy link
Contributor Author

enchev commented Feb 18, 2016

From @Daxito on February 17, 2016 19:34

Correct, this is the new default manifest generated, I just added:
uses-permission android:name="android.permission.ACCESS_NETWORK_STATE

@enchev
Copy link
Contributor Author

enchev commented Feb 18, 2016

From @NathanaelA on February 17, 2016 19:36

@rosen-vladimirov Here is the key why it is crashing so you don't have to debug it...

function getConnectivityManager() {
    return utils.ad.getApplicationContext().getSystemService(android.content.Context.CONNECTIVITY_SERVICE);
}

See the utils.ad.getApplicationContext() -- the minute you get the Application context without the Application being started it crashed. In my code Either of these two lines will cause it to crash:

    var ctx = java.lang.Class.forName("android.app.AppGlobals").getMethod("getInitialApplication", null).invoke(null, null);
    var ctx = java.lang.Class.forName("android.app.ActivityThread").getMethod("currentApplication", null).invoke(null, null);

I have a routine that initializes a plugin; if the {N} application.context isn't yet set then it uses those two methods listed above to get the actual context. This has worked since v1.2 when I first wrote the code.

@enchev
Copy link
Contributor Author

enchev commented Feb 18, 2016

From @rosen-vladimirov on February 17, 2016 19:41

Great work @NathanaelA ,
Soooo, in case you move the application.start() call before your lines, the app should work?

@enchev
Copy link
Contributor Author

enchev commented Feb 18, 2016

From @rosen-vladimirov on February 17, 2016 19:41

We'll have to check this with the runtime and modules teams. @slavchev , @hshristov any thoughts on this?

@enchev
Copy link
Contributor Author

enchev commented Feb 18, 2016

From @Daxito on February 17, 2016 19:47

Yes @rosen-vladimirov , it works if I move the start before.
Thank you all! I can use this workaround until you fix it in case it is actually broken.

@enchev
Copy link
Contributor Author

enchev commented Feb 18, 2016

From @NathanaelA on February 17, 2016 19:49

Yes. However, on iOS once you do an application.start() nothing below it is ran. ;-(

Please note, I did a quick search of the tns-core-modules for getApplicationContext() and it is used in several places like filesystem, and platform. The good news is that this bug shouldn't be too wide spread as far as I can tell. Most people probably leave their app.js file alone...

@enchev
Copy link
Contributor Author

enchev commented Feb 18, 2016

From @Daxito on February 17, 2016 19:53

Well, I can also move that to my home page instead.

@enchev
Copy link
Contributor Author

enchev commented Feb 18, 2016

From @NathanaelA on February 17, 2016 20:54

Here is a workaround I'm using in my app:

var application = require("application");
if (global.android) {
    application.start({moduleName: "main-page"});
}

// ALL my custom code including any additional requires...

if (!global.android) {
    application.start({moduleName: "main-page"});
}

@enchev
Copy link
Contributor Author

enchev commented Feb 18, 2016

Hey folks,

I've just submitted pull request related to this issue. The error in this case was caused by the fact that connectivity.getConnectionType() will try access Android application instance however the application is not yet started - this can be avoided if you call the method using launch event.

Let me know what you think!

Thanks

@enchev enchev self-assigned this Feb 18, 2016
@enchev enchev closed this as completed Feb 18, 2016
@NathanaelA

This comment was marked as abuse.

@enchev
Copy link
Contributor Author

enchev commented Feb 19, 2016

Hey @slavchev, @atanasovg Can you help here?

@enchev enchev reopened this Feb 19, 2016
@atanasovg
Copy link
Contributor

@NathanaelA You are correct - this used to work prior 1.6. The behavioral change is caused by the snapshot refactoring pull because the app.init object is now populated in the application.start method - see https://github.com/NativeScript/NativeScript/blob/master/application/application.android.ts#L300-L311. In previous versions of the modules, if you access the Android Application object before requiring the application module you will get the very same exception. Why we did this change - because V8 may not serialize external memory and everything the Runtime injects as proxies and callbacks needs to happen after the snapshot.

This exception is generally a quirk in the Runtime itself and we may have this behavior improved by simply tracking the initialization process via some initializing flag. Good news is that for 1.7 we will do our best to integrate the new Activity/Application resolution (NativeScript/android#283) and the problem will not exist with the new functionality.

Now, I guess I haven't estimated well the impact of this change - my thinking was that it shouldn't be hit by the users and obviously my assumption was wrong. Your scenarios are perfectly valid and if this turns to be a show-stopper we will definitely push a hot fix for it.

@NathanaelA

This comment was marked as abuse.

@atanasovg
Copy link
Contributor

NativeScript/android@a89aa46 fixes the issue, we need to prepare a hot fix for the Android Runtime.

@lock
Copy link

lock bot commented Aug 30, 2019

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@lock lock bot locked and limited conversation to collaborators Aug 30, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants