Custom activity java.lang.ClassNotFoundException

android

#1

Custom activity java.lang.ClassNotFoundException. I did not write custom activity as plugin.

My activity: (located in ~/app/gallery.ts)

@JavaProxy("com.island68.Activities.GalleryActivity")
export class GalleryActivity extends android.app.Activity {
    public URLs = []
    private _callbacks: AndroidActivityCallbacks

    public onBackPressed(): void {
        this._callbacks.onBackPressed(this, super.onBackPressed);
    }

    public onRequestPermissionsResult(requestCode: number, permissions: Array<String>, grantResults: Array<number>): void {
        this._callbacks.onRequestPermissionsResult(this, requestCode, permissions, grantResults, undefined /*TODO: Enable if needed*/);
    }

    protected onCreate(savedInstanceState: android.os.Bundle): void {
        if (!this._callbacks) {
            setActivityCallbacks(this);
        }
        this._callbacks.onCreate(this, savedInstanceState, super.onCreate);

        const context: android.content.Context = app.android.context;
        let layout = context.getResources().getIdentifier("activity_gallery", "layout", context.getPackageName());
        let resourceId = this.getResources().getIdentifier("scroll_gallery_view", "id", this.getPackageName())

        this.setContentView(layout);

        let getFragmentManager = app.android.startActivity.getFragmentManager()

        let mMediaGalleryView = <any>(this.findViewById(resourceId))
        mMediaGalleryView.setThumbnailSize(80)
            .setZoom(true)
            .setFragmentManager(getFragmentManager())
            .addMedia(
                ...this.URLs.map((URL) => nz.co.iswe.android.mediagallery.MediaInfo.url(URL))
            ).setCurrentItem(2);
    }

    protected onSaveInstanceState(outState: android.os.Bundle): void {
        this._callbacks.onSaveInstanceState(this, outState, super.onSaveInstanceState);
    }

    protected onStart(): void {
        this._callbacks.onStart(this, super.onStart);
    }

    protected onStop(): void {
        this._callbacks.onStop(this, super.onStop);
    }

    protected onDestroy(): void {
        this._callbacks.onDestroy(this, super.onDestroy);
    }

    protected onActivityResult(requestCode: number, resultCode: number, data: android.content.Intent): void {
        this._callbacks.onActivityResult(this, requestCode, resultCode, data, super.onActivityResult);
    }
}

My layout: (located in ~/app/App_Resources/Android/layout)

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent">
    <nz.co.iswe.android.mediagallery.MediaGalleryView
        android:id="@+id/media_gallery_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#000"/>
</LinearLayout>

My AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android" package="__PACKAGE__" android:versionCode="10000" android:versionName="1.0">
    <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.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-feature android:name="android.hardware.camera"/>
    <application android:name="com.tns.NativeScriptApplication" android:allowBackup="true" android:icon="@drawable/icon"
                 android:label="@string/app_name"
                 android:theme="@style/AppTheme"
                 android:windowSoftInputMode="adjustResize">

        <activity android:name="com.tns.NativeScriptActivity" android:label="@string/title_activity_kimera"
                  android:configChanges="keyboardHidden|orientation|screenSize" android:theme="@style/LaunchScreenTheme"
                  android:screenOrientation="portrait">
            <meta-data android:name="SET_THEME_ON_LAUNCH" android:resource="@style/AppTheme"/>
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>

        <activity android:name="com.island68.Activities.GalleryActivity"/>

        <activity android:name="com.tns.ErrorReportActivity"/>

    </application>
</manifest>

Do I need to do any thing other to make my class com.island68.Activities.GalleryActivity visible in the program? I tried both --bundle and without --bundle command, but not render class not found exception


#2

How do you start the activity, when exactly you get class not found exception?


#3

Hi, I managed to resolve ClassNotFoundException on startup problem. It is due to I put JavaProxy class and a helper function in same ts file. After I separate them to two different files. Everything work as charm.

However, I encountered another problem when actually start the activity:

my code for start the activity:

 let photosArray = new java.util.ArrayList<string>();
    URLs.forEach((URL) => {
        photosArray.add(URL);
    })

    let intent: android.content.Intent = new android.content.Intent(
        app.android.foregroundActivity,
        com.island68.Activities.GalleryActivity["class"]
    )

    intent.putStringArrayListExtra("URLs", photosArray);
    app.android.foregroundActivity.startActivity(intent);

output:

JS: ERROR TypeError: Cannot read property 'GalleryActivity' of undefined

Could you please indicate me how to properly start the activity? I have limited background on android development.

I tried method described here Switch to another (Android) Activity onTap

let intent = new android.content.Intent();
    intent.setClassName("com.island68.MapleAndroid", "com.island68.Activities.GalleryActivity");

but it not work:

System.err: java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.island68.MapleAndroid/com.island68.Activities.GalleryActivity}: java.lang.ClassNotFoundException: Didn't find class "com.island68.Activities.GalleryActivity" on path: DexPathList[[zip file "/data/app/com.island68.MapleAndroid-1/base.apk"],nativeLibraryDirectories=[/data/app/com.island68.MapleAndroid-1/lib/arm, /data/app/com.island68.MapleAndroid-1/base.apk!/lib/armeabi-v7a, /vendor/lib, /system/lib]]

#4

Are you building with --bundle or without?


#5

No, I’m not.

I got same error when execute console.dir((com as any).island68.Activities.GalleryActivity)

I’ll repost my code for better clarity:

Custom Activity (~/app/gallery.activity.android.ts)

import * as app from "application";
import { AndroidActivityCallbacks, setActivityCallbacks } from "ui/frame";

declare var nz: any

@JavaProxy("com.island68.Activities.GalleryActivity")
class Activity extends android.app.Activity {
    public URLs = []

    private _callbacks: AndroidActivityCallbacks;

    protected onCreate(savedInstanceState: android.os.Bundle): void {
        if (!this._callbacks) {
            setActivityCallbacks(this);
        }
        this._callbacks.onCreate(this, savedInstanceState, super.onCreate);


        const context: android.content.Context = app.android.context;
        let layout = context.getResources().getIdentifier("activity_gallery", "layout", context.getPackageName());
        let resourceId = context.getResources().getIdentifier("scroll_gallery_view", "id", context.getPackageName())

        this.setContentView(layout);

        let getFragmentManager = app.android.startActivity.getFragmentManager()

        let mMediaGalleryView = <any>(this.findViewById(resourceId))
        mMediaGalleryView.setThumbnailSize(80)
            .setZoom(true)
            .setFragmentManager(getFragmentManager())
            .addMedia(
                ...this.URLs.map((URL) => nz.co.iswe.android.mediagallery.MediaInfo.url(URL))
            ).setCurrentItem(2);
    }

    protected onSaveInstanceState(outState: android.os.Bundle): void {
        this._callbacks.onSaveInstanceState(this, outState, super.onSaveInstanceState);
    }

    protected onStart(): void {
        this._callbacks.onStart(this, super.onStart);
    }

    protected onStop(): void {
        this._callbacks.onStop(this, super.onStop);
    }

    protected onDestroy(): void {
        this._callbacks.onDestroy(this, super.onDestroy);
    }

    public onBackPressed(): void {
        this._callbacks.onBackPressed(this, super.onBackPressed);
    }

    public onRequestPermissionsResult(requestCode: number, permissions: Array<String>, grantResults: Array<number>): void {
        this._callbacks.onRequestPermissionsResult(this, requestCode, permissions, grantResults, undefined /*TODO: Enable if needed*/);
    }

    protected onActivityResult(requestCode: number, resultCode: number, data: android.content.Intent): void {
        this._callbacks.onActivityResult(this, requestCode, resultCode, data, super.onActivityResult);
    }
}

trigger method: (~/app/gallery.ts)

import * as app from "application";

declare var com: any

export function showGallery(URLs: string[]) {
    console.log("TRY TO LOG")
    console.dir((com as any).island68.Activities.GalleryActivity) // <-- error here

    // let photosArray = new java.util.ArrayList<string>();
    // URLs.forEach((URL) => {
    //     photosArray.add(URL);
    // })
    //
    // let intent = new android.content.Intent();
    // intent.setClassName("com.island68.MapleAndroid", "com.island68.Activities.GalleryActivity");
    //
    // // let intent: android.content.Intent = new android.content.Intent(
    // //     app.android.foregroundActivity,
    // //     com.island68.Activities.GalleryActivity["class"]
    // // )
    //
    // intent.putStringArrayListExtra("URLs", photosArray);
    // app.android.foregroundActivity.startActivity(intent);
}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android" package="__PACKAGE__" android:versionCode="10000" android:versionName="1.0">
    <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.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-feature android:name="android.hardware.camera"/>

    <application android:name="com.tns.NativeScriptApplication" android:allowBackup="true" android:icon="@drawable/icon"
                 android:label="@string/app_name"
                 android:theme="@style/AppTheme"
                 android:windowSoftInputMode="adjustResize">

        <activity android:name="com.tns.NativeScriptActivity" android:label="@string/title_activity_kimera"
                  android:configChanges="keyboardHidden|orientation|screenSize" android:theme="@style/LaunchScreenTheme"
                  android:screenOrientation="portrait">
            <meta-data android:name="SET_THEME_ON_LAUNCH" android:resource="@style/AppTheme"/>
            <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"/>
        <activity android:name="com.island68.Activities.GalleryActivity"/>

    </application>

</manifest>


#6

Are you trying to add a new activity or customize NativeScript activity, you have to add callbacks only if you are customizing NativeScript activity.

You are using Core / Angular for development?


#7

I’m using angular and to add a new activity to display remote image gallery.

I changed my activity into

import * as app from "application";

declare var nz: any

//@ts-ignore
@JavaProxy("com.island68.Activities.GalleryActivity")
class Activity extends android.app.Activity {
    public URLs = []

    protected onCreate(bundle) {
        super.onCreate(bundle);

        const context: android.content.Context = app.android.context;
        let layout = context.getResources().getIdentifier("activity_gallery", "layout", context.getPackageName());
        let resourceId = context.getResources().getIdentifier("scroll_gallery_view", "id", context.getPackageName())

        this.setContentView(layout);

        let getFragmentManager = app.android.startActivity.getFragmentManager()

        let mMediaGalleryView = <any>(this.findViewById(resourceId))
        mMediaGalleryView.setThumbnailSize(80)
            .setZoom(true)
            .setFragmentManager(getFragmentManager())
            .addMedia(
                ...this.URLs.map((URL) => nz.co.iswe.android.mediagallery.MediaInfo.url(URL))
            ).setCurrentItem(2);
    }
}

but still same error


#8

Did you check the Android’s compiled source folder, does the GalleryActivity.java exists?


#9

where should it located?


#10

I just checked, the file is not existed


#11

It must create a Java file then only your activity will work. Try just importing the file in main.ts and see if Java file is created then, to make sure the file is not skipped by compiler.


#12

After spending hours of debugging, the issue is origin from import * as app from "application"
change to require method resolve the problem