Skip to content
This repository was archived by the owner on Aug 7, 2021. It is now read-only.

Snapshot Bundle failed with custom android activity #568

Closed
9 tasks done
RadouaneRoufid opened this issue Jun 15, 2018 · 6 comments
Closed
9 tasks done

Snapshot Bundle failed with custom android activity #568

RadouaneRoufid opened this issue Jun 15, 2018 · 6 comments

Comments

@RadouaneRoufid
Copy link

Issue Checklist

Tell us about the problem

I'm using a custom android activity in my nativescript project.

@JavaProxy("org.myApp.MainActivity")
class Activity extends android.support.v7.app.AppCompatActivity {
...
}

I declared this activity in my AndroidManifest.xml as below

<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="org.myApp.MainActivity"
                android:launchMode="singleTask"
                android:label="@string/title_activity_kimera"
                android:configChanges="keyboardHidden|orientation|screenSize"
                android:theme="@style/LaunchScreenTheme">
...

I added this activity in webpack.config.js

    // Add your custom Activities, Services and other Android app components here.
    const appComponents = [
        "tns-core-modules/ui/frame",
        "tns-core-modules/ui/frame/activity",
        resolve(__dirname, "app/activity.android.ts"),
    ];

Building with: tns build android --bundle --env.aot --env.uglify --env.snapshot results with the following error:

Warning: there already is an extend called org.myApp.MainActivity.
Warning: The static binding generator will generate extend from:vendor.js implementation
Exception in thread "main" java.io.IOException: File already exists. This may lead to undesired behavior.
Please change the name of one of the extended classes.
File:/home/ruser/IdeaProjects/deepan/deepan-parent/deepan-front/src/gui/nativescript/platforms/android/app/src/main/java/org/myApp/MainActivity.java Class: org.myApp.MainActivity
        at org.nativescript.staticbindinggenerator.Generator.writeBindings(Generator.java:78)
        at org.nativescript.staticbindinggenerator.Main.main(Main.java:48)

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:runSbg'.
> Process 'command '/usr/lib/jvm/java-8-oracle/bin/java'' finished with non-zero exit value 1

Local environment

  • Platform Linux
  • Node version 8.11.2
  • NativeScript CLI version 4.1.0

Project data

  • Platform you are building the app for Android
  • Node dependencies:
"dependencies": {
    "@angular/animations": "~5.2.1",
    "@angular/common": "^5.2.1",
    "@angular/compiler": "^5.2.1",
    "@angular/core": "^5.2.1",
    "@angular/forms": "^5.2.1",
    "@angular/http": "^5.2.1",
    "@angular/platform-browser": "^5.2.1",
    "@angular/platform-browser-dynamic": "^5.2.1",
    "@angular/router": "^5.2.1",
    "@ngrx/effects": "^4.1.1",
    "@ngrx/router-store": "^4.1.1",
    "@ngrx/store": "^4.1.1",
    "@ngx-translate/core": "^9.1.1",
    "@ngx-translate/http-loader": "^2.0.1",
    "arrive": "^2.3.1",
    "core-js": "^2.5.2",
    "font-awesome": "4.7.0",
    "fs": "0.0.1-security",
    "hammerjs": "^2.0.8",
    "lodash": "^4.17.4",
    "nativescript-angular": "~5.2.0",
    "nativescript-background-http": "^3.2.7",
    "nativescript-bottom-navigation": "^1.1.2",
    "nativescript-bottombar": "^3.0.8",
    "nativescript-cardview": "^2.0.5",
    "nativescript-checkbox": "^3.0.3",
    "nativescript-floatingactionbutton": "^4.1.3",
    "nativescript-fresco": "^3.0.2",
    "nativescript-imagepicker": "^5.0.0",
    "nativescript-localstorage": "^1.1.5",
    "nativescript-mediafilepicker": "^1.0.5",
    "nativescript-modal-datetimepicker": "^1.1.0",
    "nativescript-ng-shadow": "^2.1.0",
    "nativescript-oauth": "^2.1.2",
    "nativescript-phone": "^1.3.1",
    "nativescript-photoviewer": "^1.4.0",
    "nativescript-snackbar": "^2.0.0",
    "nativescript-theme-core": "~1.0.4",
    "nativescript-ui-listview": "^3.5.7",
    "nativescript-ui-sidedrawer": "^4.1.1",
    "ng2-validation": "^4.2.0",
    "ngrx-store-freeze": "^0.1.9",
    "node-sass": "^4.9.0",
    "npm": "^4.2.0",
    "osenv": "^0.1.4",
    "path": "^0.12.7",
    "reflect-metadata": "^0.1.12",
    "rxjs": "^5.5.5",
    "tns-core-modules": "~4.1.0",
    "url": "^0.11.0",
    "zone.js": "0.8.5"
  },
  "devDependencies": {
    "@angular-devkit/core": "~0.6.3",
    "@angular/compiler-cli": "^5.2.1",
    "@ngtools/webpack": "~6.0.3",
    "@types/googlemaps": "^3.30.8",
    "@types/jasmine": "^2.8.5",
    "babel-traverse": "6.26.0",
    "babel-types": "6.26.0",
    "babylon": "6.18.0",
    "clean-webpack-plugin": "~0.1.19",
    "copy-webpack-plugin": "~4.5.1",
    "css-loader": "~0.28.11",
    "del": "^2.2.2",
    "extract-text-webpack-plugin": "~3.0.2",
    "fs-walk": "0.0.2",
    "gulp": "^4.0.0",
    "gulp-debug": "^3.1.0",
    "gulp-exec": "^3.0.1",
    "gulp-if": "^2.0.2",
    "gulp-rename": "^1.2.2",
    "gulp-spawn": "^0.4.0",
    "gulp-string-replace": "^0.4.0",
    "lazy": "1.0.11",
    "mkdirp": "^0.5.1",
    "nativescript-dev-sass": "^1.6.0",
    "nativescript-dev-typescript": "~0.7.0",
    "nativescript-dev-webpack": "^0.12.0",
    "nativescript-hook": "^0.2.4",
    "nativescript-worker-loader": "~0.9.0",
    "raw-loader": "~0.5.1",
    "resolve-url-loader": "~2.3.0",
    "run-sequence": "^2.2.1",
    "sass-loader": "~7.0.1",
    "tns-platform-declarations": "^4.1.0",
    "typescript": "~2.7.2",
    "typescript-register": "^1.1.0",
    "uglifyjs-webpack-plugin": "~1.2.5",
    "webpack": "~4.6.0",
    "webpack-bundle-analyzer": "~2.13.0",
    "webpack-cli": "~2.1.3",
    "webpack-sources": "~1.1.0"
  }
  • Webpack configuration:
const { join, relative, resolve, sep } = require("path");

const webpack = require("webpack");
const nsWebpack = require("nativescript-dev-webpack");
const nativescriptTarget = require("nativescript-dev-webpack/nativescript-target");
const CleanWebpackPlugin = require("clean-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer");
const { NativeScriptWorkerPlugin } = require("nativescript-worker-loader/NativeScriptWorkerPlugin");
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");

module.exports = env => {
    // Add your custom Activities, Services and other Android app components here.
    const appComponents = [
        "tns-core-modules/ui/frame",
        "tns-core-modules/ui/frame/activity",
        resolve(__dirname, "app/activity.android.ts"),
    ];

    const platform = env && (env.android && "android" || env.ios && "ios");
    if (!platform) {
        throw new Error("You need to provide a target platform!");
    }

    const platforms = ["ios", "android"];
    const projectRoot = __dirname;
    nsWebpack.loadAdditionalPlugins({ projectDir: projectRoot });

    // Default destination inside platforms/<platform>/...
    const dist = resolve(projectRoot, nsWebpack.getAppPath(platform, projectRoot));
    const appResourcesPlatformDir = platform === "android" ? "Android" : "iOS";

    const {
        // The 'appPath' and 'appResourcesPath' values are fetched from
        // the nsconfig.json configuration file
        // when bundling with `tns run android|ios --bundle`.
        appPath = "app",
        appResourcesPath = "app/App_Resources",

        // You can provide the following flags when running 'tns run android|ios'
        aot, // --env.aot
        snapshot, // --env.snapshot
        uglify, // --env.uglify
        report, // --env.report
    } = env;

    const appFullPath = resolve(projectRoot, appPath);
    const appResourcesFullPath = resolve(projectRoot, appResourcesPath);

    const entryModule = aot ?
        nsWebpack.getAotEntryModule(appFullPath) : 
        `${nsWebpack.getEntryModule(appFullPath)}.ts`;
    const entryPath = `.${sep}${entryModule}`;

    const config = {
        mode: uglify ? "production" : "development",
        context: appFullPath,
        watchOptions: {
            ignored: [
                appResourcesFullPath,
                // Don't watch hidden files
                "**/.*",
            ]
        },
        target: nativescriptTarget,
        entry: {
            bundle: entryPath,
        },
        output: {
            pathinfo: false,
            path: dist,
            libraryTarget: "commonjs2",
            filename: "[name].js",
            globalObject: "global",
        },
        resolve: {
            extensions: [".ts", ".js", ".scss", ".css"],
            // Resolve {N} system modules from tns-core-modules
            modules: [
                resolve(__dirname, "node_modules/tns-core-modules"),
                resolve(__dirname, "node_modules"),
                "node_modules/tns-core-modules",
                "node_modules",
            ],
            alias: {
                '~': appFullPath
            },
            symlinks: true
        },
        resolveLoader: {
            symlinks: false
        },
        node: {
            // Disable node shims that conflict with NativeScript
            "http": false,
            "timers": false,
            "setImmediate": false,
            "fs": "empty",
            "__dirname": false,
        },
        devtool: "none",
        optimization: {
            splitChunks: {
                cacheGroups: {
                    vendor: {
                        name: "vendor",
                        chunks: "all",
                        test: (module, chunks) => {
                            const moduleName = module.nameForCondition ? module.nameForCondition() : '';
                            return /[\\/]node_modules[\\/]/.test(moduleName) ||
                                    appComponents.some(comp => comp === moduleName);
                        },
                        enforce: true,
                    },
                }
            },
            minimize: !!uglify,
            minimizer: [
                new UglifyJsPlugin({
                    uglifyOptions: {
                        parallel: true,
                        cache: true,
                        output: {
                            comments: false,
                        },
                        compress: {
                            // The Android SBG has problems parsing the output
                            // when these options are enabled
                            'collapse_vars': platform !== "android",
                            sequences: platform !== "android",
                        }
                    }
                })
            ],
        },
        module: {
            rules: [
                {
                    test: new RegExp(entryPath),
                    use: [
                        // Require all Android app components
                        platform === "android" && {
                            loader: "nativescript-dev-webpack/android-app-components-loader",
                            options: { modules: appComponents }
                        },

                        {
                            loader: "nativescript-dev-webpack/bundle-config-loader",
                            options: {
                                registerPages: false,
                                loadCss: !snapshot, // load the application css if in debug mode
                            }
                        },
                    ].filter(loader => !!loader)
                },

                { test: /\.html$|\.xml$/, use: "raw-loader" },

                // tns-core-modules reads the app.css and its imports using css-loader
                {
                    test: /[\/|\\]app\.css$/,
                    use: {
                        loader: "css-loader",
                        options: { minimize: false, url: false },
                    }
                },
                {
                    test: /[\/|\\]app\.scss$/,
                    use: [
                        { loader: "css-loader", options: { minimize: false, url: false } },
                        "sass-loader"
                    ]
                },

                // Angular components reference css files and their imports using raw-loader
                { test: /\.css$/, exclude: /[\/|\\]app\.css$/, use: "raw-loader" },
                { test: /\.scss$/, exclude: /[\/|\\]app\.scss$/, use: ["raw-loader", "resolve-url-loader", "sass-loader"] },

                // Compile TypeScript files with ahead-of-time compiler.
                {
                    test: /.ts$/, use: [
                        "nativescript-dev-webpack/moduleid-compat-loader",
                        "@ngtools/webpack",
                    ]
                },

                // Mark files inside `@angular/core` as using SystemJS style dynamic imports.
                // Removing this will cause deprecation warnings to appear.
                {
                    test: /[\/\\]@angular[\/\\]core[\/\\].+\.js$/,
                    parser: { system: true },
                },
            ],
        },
        plugins: [
            // Define useful constants like TNS_WEBPACK
            new webpack.DefinePlugin({
                "global.TNS_WEBPACK": "true",
            }),
            // Remove all files from the out dir.
            new CleanWebpackPlugin([ `${dist}/**/*` ]),
            // Copy native app resources to out dir.
            new CopyWebpackPlugin([
                {
                    from: `${appResourcesFullPath}/${appResourcesPlatformDir}`,
                    to: `${dist}/App_Resources/${appResourcesPlatformDir}`,
                    context: projectRoot
                },
            ]),
            // Copy assets to out dir. Add your own globs as needed.
            new CopyWebpackPlugin([
                { from: "fonts/**" },
                { from: "**/*.jpg" },
                { from: "**/*.png" },
                { from: "assets/i18n/*.json" },
            ], { ignore: [`${relative(appPath, appResourcesFullPath)}/**`] }),
            // Generate a bundle starter script and activate it in package.json
            new nsWebpack.GenerateBundleStarterPlugin([
                "./vendor",
                "./bundle",
            ]),
            // For instructions on how to set up workers with webpack
            // check out https://github.com/nativescript/worker-loader
            new NativeScriptWorkerPlugin(),
            // AngularCompilerPlugin with augmented NativeScript filesystem to handle platform specific resource resolution.
            new nsWebpack.NativeScriptAngularCompilerPlugin({
                entryModule: resolve(appPath, "app.module#AppModule"),
                tsConfigPath: join(__dirname, "tsconfig.esm.json"),
                skipCodeGeneration: !aot,
                platformOptions: {
                    platform,
                    platforms,
                },
            }),
            // Does IPC communication with the {N} CLI to notify events when running in watch mode.
            new nsWebpack.WatchStateLoggerPlugin(),
        ],
    };

    if (report) {
        // Generate report files for bundles content
        config.plugins.push(new BundleAnalyzerPlugin({
            analyzerMode: "static",
            openAnalyzer: false,
            generateStatsFile: true,
            reportFilename: resolve(projectRoot, "report", `report.html`),
            statsFilename: resolve(projectRoot, "report", `stats.json`),
        }));
    }

    if (snapshot) {
        config.plugins.push(new nsWebpack.NativeScriptSnapshotPlugin({
            chunk: "vendor",
            requireModules: [
                "reflect-metadata",
                "@angular/platform-browser",
                "@angular/core",
                "@angular/common",
                "@angular/router",
                "nativescript-angular/platform-static",
                "nativescript-angular/router",
            ],
            projectRoot,
            webpackConfig: config,
        }));
    }

    return config;
};

@vchimev
Copy link
Contributor

vchimev commented Jun 16, 2018

Hey @RadouaneRoufid,

I've tried to reproduce this issue with my android-extend-ng sample app, but to no avail.
Are you able to replicate the problem with this project at your end?

@RadouaneRoufid
Copy link
Author

Hi @vchimev

I changed resolve(__dirname, "app/activity.android.ts"), to "./activity.android.ts" in my webpack.config.js and build is done correctly now with a warning.

Warning: there already is an extend called org.myApp.MainActivity.
Warning: The static binding generator will generate extend from:bundle.js implementation

I'm using nativescript-dev-webpack 0.12.0. I will migrate to 0.13.0 as in android-extend-ng.

Thank you for your reactivity !

@RadouaneRoufid
Copy link
Author

I have a little question @vchimev. I need to import my custoMActivity in my app.component. The problem is in dev mode, I need to import from import {whatever} from "./activity.android"; and in bundle mode // import {whatever} from "./activity";

How can i handle this scenario ?

@vchimev
Copy link
Contributor

vchimev commented Jun 18, 2018

Hey @RadouaneRoufid,

The right way is to add a common d.ts file for the platform-specific file. I gave it a try in this commit. Also, here is a descriptive comment on this topic.

@vchimev vchimev closed this as completed Jun 19, 2018
@vchimev vchimev removed their assignment Jun 19, 2018
@vchimev
Copy link
Contributor

vchimev commented Jun 23, 2018

Hey @RadouaneRoufid,

Let me follow up that adding a custom android app component to the array on the top of the webpack.config.js file should be resolved to an absolute path, i.e.
resolve(__dirname, "app/activity.android.ts") in order to be included in the common vendor.js chunk. Adding it by a relative path is only a workaround for this issue on Windows, which fix is on a pull request.

In regard to the original problem with build failed, you reported, I updated all the demos in the branch for the fix above to extend android activity and application, and managed to execute them successfully, not reproducing the problem.

Do you still experience it?

@RadouaneRoufid
Copy link
Author

RadouaneRoufid commented Jun 25, 2018

I'm still using "nativescript-dev-webpack": "^0.12.0" which requires a relative path to activity.android.ts on linux platform.

const appComponents = [
        "tns-core-modules/ui/frame",
        "tns-core-modules/ui/frame/activity",
        "./activity.android.ts",
    ];

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants