NativeScript Bundle Snapshot - ReferenceError: com is not defined - android

I'm trying to bundle a NativeScript App with the snapshot flag like this:
tns build android --bundle --env.snapshot
The following error appears:
ERROR in NativeScriptSnapshot. Snapshot generation failed!
Target architecture: x86
# Script run failed in <embedded>#736:2461
ReferenceError: com is not defined
#
# Fatal error in ../src/snapshot/mksnapshot.cc, line 175
# Check failed: blob.data.
#
Anyone have an idea how to fix that?

The problem was that the app.scss in the root folder had been renamed to something else. Make sure it it will pass the regex ( default: /^\.\/app\.(css|scss|less|sass)$/ ) in the vendor.ts file.

See How it works part
Modules included in the snapshotted bundle can still contain native
API calls given that they are not evaluated immediately upon module
loading. For example, the following module:
require("application");
var time = new android.text.format.Time(); can’t be snapshotted
because it touches android.text.format.Time API which is not
available. However, in this one:
require("application");
function getTime() {
return new android.text.format.Time(); } the native API access is not evaluated on module execution. Given that getTime() is called
later in the fully featured V8 context provided by the Android
runtime, we are safe to include the module in the snapshotted bundle.
If the snapshotting step fails because of a reference to an undefined
API, try some of the following solutions:
If you can change the module containing the forbidden API call, wrap
the guilty code in a function that is called once the app is running
on device Keep the module in the bundle but make sure all require
calls of the non-snapshotable module are executed once the app is
running on device: require("application"); var m =
require("non-snapshotable-module");
function doSomething() {
return m.someMethod(); } The code above has a higher chance to be successfully snapshotted if it loads the non-snapshotable module when
it actually needs it:
require("application");
function doSomething() {
return require("non-snapshotable-module").someMethod(); } If doSomething() function is never called in snapshot context, the
non-snapshotable module will not be evaluated and blob generation will
succeed.
Exclude the module containing the forbidden API call from the
snapshotted bundle.
So make sure you are not referencing com in snapshot time.

Related

Android: after Gradle update to 6.7.1 ClassLoader in JUnit test no longer lists all resources

I need to iterate over specific classes from main package in my android unit test, to check some of their properties.
For this I use standard approach, using ClassLoader:
val classLoader = Thread.currentThread().contextClassLoader
val resources: Enumeration<URL> = classLoader.getResources("com/models/package")
assert(resources.hasMoreElements()) // Fails from CL, works in AS
Before the Gradle update (had Gradle 5.6.4) that worked. Now the behaviour is as follows: it works when test is run from Android Studio, but fails (returns empty enumeration) when run from command line with gradlew.
I wonder what might be the difference in this respect between the two Gradle versions? And why it still works when run from Studio?
Some considerations and things I have tried:
Referencing these classes in unit test works ok, and also classLoader.findClass("com.models.package.MyModel") and
classLoader.loadClass("com.models.package.MyModel") from unit test is working. But even after that classLoader.getResources("com/models/package") returns empty enumeration.
Using other references to ClassLoader, like MyModel::class.java.classLoader and ClassLoader.getSystemClassLoader() didn't make any difference.
Gradle build from command line contains the warning "OpenJDK 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended", but as far as I can tell it's not connected to my issue.
If I put some of the classes from 'com/models/package' to the unit test /test folder, they are getting returned in enumeration.
This might be connected with some new optimisation setting that makes ClassLoaders omit registering some of the classes, in different root directories, but as it still works in AS there might be some setting to turn this optimisation off in a command line build also?
Thank you for any suggestions on this.
In Gradle 6.7.1 I had to include the directory with the code to the test sourceSets. Afterwards the classloader from junit started to see the classes and return them in Enumeration.
sourceSets {
test {
java.srcDirs += ['src/main']
}
}

NUnit Test Project - Unable to create Xamarin MockContext - java-interop could not be found

I have an NUnit test project which works fine on its own until I start trying to bring Xamarin into the mix. Here is what my test looks like just to start:
[Test]
public void Test1()
{
//ARRANGE
var mockContext = new Android.Test.Mock.MockContext();
var textView = new Android.Widget.TextView(mockContext);
//ASSERT
var response = 1;
Assert.AreEqual(1, response);
}
This compiles fine, but when I run it, I get an error from the first line:
Message: System.DllNotFoundException : Unable to load DLL 'java-interop' or one of its dependencies: The specified module could not be found. (Exception from HRESULT: 0x8007007E)
I have verified that this reference java.interop is included in the project and also confirmed that the .dll is in the location on the drive that the reference is pointing to:
Is it just not possible to create instances of Xamarin objects in the NUnit test project?
I've seen this brought up numerous times from my research but the conclusion is usually along the lines of "Not sure if its possible, just avoid referencing Xamarin" Does anyone know for sure?

How to use an external sdk with Nativescript

I'm developping a NativeScript application and want to use the WonderPush SDK. I've already used this SDK into a native Android application, so I tried to create a new plugin to wrap the SDK.
I imported the library in the gradle file, and I tried to call the library from the NativeScript plugin. But the library is empty, if I tried to log it with console.dir, the only result is an quasi-empty object:
export class NativescriptWonderpush extends Common {
init() {
console.dir(com.wonderpush);
// com.wonderpush.sdk.Wonderpush.initialize(app.android.context);
}
}
JS: ==== object dump start ====
JS: sdk: {}
JS: ==== object dump end ====
(The second line com.wonderpush.sdk.Wonderpush.initialize() crash because com.wonderpush.sdk is empty)
Thanks for your help
Native objects may not always be traceable in console like JS objects.
Though you could refer their docs and call the methods you like Or even generate typings if you are using TypeeScript by following the steps given here. The typings ensure that the classes, methods, properties etc., are public and accessible to the JS runtime.

Scala reflection java.rmi dependency, can it work on Android?

I would like to use the Scala (2.11) reflection package's runtime mirror in a Scala application compiled for android which is being build using Scala on android.
I was able to fiddle with ProGuard options in order to make it include the required Scala classes. However when I try to get a mirror instance:
universe.runtimeMirror(this.getClass.getClassLoader)
(Indeed it fails during the lazy computation of universe)
The application crashes in run time:
java.lang.NoClassDefFoundError: Failed resolution of: Ljava/rmi/Remote;
at scala.reflect.internal.Definitions$DefinitionsClass.RemoteInterfaceClass$lzycompute(Definitions.scala:370)
at scala.reflect.internal.Definitions$DefinitionsClass.RemoteInterfaceClass(D efinitions.scala:370)
at scala.reflect.runtime.JavaUniverseForce$class.force(JavaUniverseForce.scal a:255)
at scala.reflect.runtime.JavaUniverse.force(JavaUniverse.scala:16)
at scala.reflect.runtime.JavaUniverse.init(JavaUniverse.scala:147)
at scala.reflect.runtime.JavaUniverse.<init>(JavaUniverse.scala:78)
at scala.reflect.runtime.package$.universe$lzycompute(package.scala:17)
at scala.reflect.runtime.package$.universe(package.scala:17)
This crash is for me as expected as it isn't:
It is expected as java.rmi is not part of the Android API and I should expect any code trying to load its classes to crash.
It is unexpected as I didn't know that Scala's reflect package used java.rmi
I have traced the code to were rmi is required, that is to JavaUniverse (a trait mixed in JavaUniverse class) force method:
...
definitions.RemoteInterfaceClass
...
Which leads to DefinitionsClass:
lazy val RemoteInterfaceClass = requiredClass[java.rmi.Remote]
Am I wrong to think that this is a no-go for Scala reflection in Android?
If I am, what could be a workaround to this problem?
To summarize your solution and a related solution, it is sufficient to add two files, and modify build.sbt to include:
dexAdditionalParams in Android += "--core-library"
Add java/rmi/Remote.java to your project with the content:
package java.rmi;
public interface Remote {}
Add java/rmi/RemoteException.java to your project with the content:
package java.rmi;
public interface RemoteException {}

Android bug: how to stay on Android error page about "method not mocked"?

When "not mocked" error occurs, error message referencign the following page:
http://g.co/androidstudio/not-mocked
But this page has redirect to somewhere else so I have no time to read about an error. On the redirected page, although, an error is not covered.
It can help you: Unit testing on Android Studio: "not mocked" error
Text from your link(sorry, i can't set this post as a comment) :
Note that when running tests from Gradle, we will execute tests for
every variant of your code (see here). This means that tests will end
up executing at least twice (once with the release build of your code,
once with the debug build of production code).
"Method ... not mocked."
The android.jar file that is used to run unit tests does not contain
any actual code - that is provided by the Android system image on real
devices. Instead, all methods throw exceptions (by default). This is
to make sure your unit tests only test your code and do not depend on
any particular behaviour of the Android platform (that you have not
explicitly mocked e.g. using Mockito). If that proves problematic, you
can add the snippet below to your build.gradle to change this
behavior:
android {
// ...
testOptions {
unitTests.returnDefaultValues = true
}
}
We are aware that the default behavior is problematic when using
classes like Log or TextUtils and will evaluate possible solutions in
future releases.

Categories

Resources