Advertisement
Help Keep Boards Alive. Support us by going ad free today. See here: https://subscriptions.boards.ie/.
If we do not hit our goal we will be forced to close the site.

Current status: https://keepboardsalive.com/

Annual subs are best for most impact. If you are still undecided on going Ad Free - you can also donate using the Paypal Donate option. All contribution helps. Thank you.
https://www.boards.ie/group/1878-subscribers-forum

Private Group for paid up members of Boards.ie. Join the club.

Changing package name breaks app?

  • 19-11-2012 04:33PM
    #1
    Moderators, Science, Health & Environment Moderators, Social & Fun Moderators, Society & Culture Moderators Posts: 60,119 Mod ✭✭✭✭


    Hey, I have a working app with some native components. When I change the package name the app doesn't run any more. No errors until I run, where I get strange 'cannot inflate' errors. it's definitely something got to do with building the native stuff, any ideas on how to keep it working?

    R9zqW.png


Comments

  • Registered Users, Registered Users 2 Posts: 18,272 ✭✭✭✭Atomic Pineapple


    Which package name are you changing?


  • Moderators, Science, Health & Environment Moderators, Social & Fun Moderators, Society & Culture Moderators Posts: 60,119 Mod ✭✭✭✭Tar.Aldarion


    jackpal.androidterm, jackpal.androidterm.compat, jackpal.androidterm.util. All three packages. I got this working before by just making a new project and copying in every file manually, and changing source code by hand, which is just slow and a bad way of doing things. In the pic I believe I was renaming jackpal.androidterm.


  • Registered Users, Registered Users 2 Posts: 7,157 ✭✭✭srsly78


    Check the ant stuff that does the JNI binding (ie the bit where the c++ talks to the java). Somewhere in there must be a reference to the old package name. Check the logs in detail as you build.


  • Moderators, Science, Health & Environment Moderators, Social & Fun Moderators, Society & Culture Moderators Posts: 60,119 Mod ✭✭✭✭Tar.Aldarion


    Thanks, I'll keep looking through that kinda stuff, just rather annoying. Even if I rerun the ant commands and the build script its the same thing.

    Here is the error I get anyway so it looks like it's trying to use the old package name all right.

    IsaKN.png


  • Registered Users, Registered Users 2 Posts: 7,157 ✭✭✭srsly78


    It seems an XML file is still referencing the old package. Is this one of your view layouts? Check your gui xml stuff for the old package.


  • Advertisement
  • Moderators, Science, Health & Environment Moderators, Social & Fun Moderators, Society & Culture Moderators Posts: 60,119 Mod ✭✭✭✭Tar.Aldarion


    Woops! that was an error i had already fixed, it was the xml reference for that one, this is what I meant to put up

    sU37F.png

    Maybe it's that i have to remake this .so file?


  • Registered Users, Registered Users 2 Posts: 7,157 ✭✭✭srsly78


    Possibly. Grep everything for the old package name is what I would do... Sorry can't really help more without being able to poke at it mself.


  • Moderators, Science, Health & Environment Moderators, Social & Fun Moderators, Society & Culture Moderators Posts: 60,119 Mod ✭✭✭✭Tar.Aldarion


    Sure thanks a lot. I'll just keep trying to find it. :) it did warn me in the first screen shot that it would break that .Exec after all. Sigh.


  • Moderators, Science, Health & Environment Moderators, Social & Fun Moderators, Society & Culture Moderators Posts: 60,119 Mod ✭✭✭✭Tar.Aldarion


    Still having problems with this, I think I need to remake a native library. However when i go to run an update script I get
     ./update.sh 
    Updating android project files
    Updated local.properties
    No project name specified, using Activity name 'Term'.
    If you wish to change it, edit the first line of build.xml.
    Added file /home/paul/Downloads/Android-Terminal-Emulator-master/tools/build.xml
    Added file /home/paul/Downloads/Android-Terminal-Emulator-master/tools/proguard-project.txt
    It seems that there are sub-projects. If you want to update them
    please use the --subprojects parameter.
    Updated local.properties
    No project name specified, using Activity name 'IntentSampleActivity'.
    If you wish to change it, edit the first line of build.xml.
    Added file /home/paul/Downloads/Android-Terminal-Emulator-master/examples/intents/build.xml
    Updated file /home/paul/Downloads/Android-Terminal-Emulator-master/examples/intents/proguard-project.txt
    Error: The project either has no target set or the target is invalid.
    Please provide a --target to the 'android update' command.
    Error: The project either has no target set or the target is invalid.
    Please provide a --target to the 'android update' command.
    Error: The project either has no target set or the target is invalid.
    Please provide a --target to the 'android update' command.
    Error: The project either has no target set or the target is invalid.
    Please provide a --target to the 'android update' command.
    It seems that there are sub-projects. If you want to update them
    please use the --subprojects parameter.
    Error: The project either has no target set or the target is invalid.
    Please provide a --target to the 'android update' command.
    


    Grrr, it never just works.


    If I ignore this and go to the project folder and run 'ndk-build' it seems to make the library anyway.

    Bu then when I run the app I get an error:
    11-20 12:30:05.249: W/dalvikvm(1536): JNI_OnLoad returned bad version (-1) in /data/data/com.example/lib/libjackpal-androidterm4.so 0x41615108
    


  • Registered Users, Registered Users 2 Posts: 7,157 ✭✭✭srsly78


    One more thing to check: look at the filenames for the generated JNI interface files. The java package name may be reflected in the c++ header name.

    For example, you might have a file called com_cheez_burger_JNI.h. If you renamed the package this might break. Could be a simple fix? The NDK stuff is supposed to autogenerate these bindings somehow.


  • Advertisement
  • Moderators, Science, Health & Environment Moderators, Social & Fun Moderators, Society & Culture Moderators Posts: 60,119 Mod ✭✭✭✭Tar.Aldarion


    Thanks, I had changed those names and I think that is some of the problem, because even though I changed them the old names are what is appearing in log cat

    http://i.imgur.com/9UrPk.png

    'cant find jackpal/androidterm/exec'

    I have already changed that so why is it looking for it?!


  • Moderators, Science, Health & Environment Moderators, Social & Fun Moderators, Society & Culture Moderators Posts: 60,119 Mod ✭✭✭✭Tar.Aldarion


    I think i am building 'libjackpal-androidterm4.so' wrong or something, as it keeps pointing to that. I wold have though changing those jni files paths would have solved that.


  • Registered Users, Registered Users 2 Posts: 7,157 ✭✭✭srsly78


    jackpal/androidterm/exec looks like a script, what is in this? Is the package name hardcoded in there somewhere?


  • Moderators, Science, Health & Environment Moderators, Social & Fun Moderators, Society & Culture Moderators Posts: 60,119 Mod ✭✭✭✭Tar.Aldarion


    I think it's just the classpath of the Exec.java file. I'll stick up the .cpp file and the .java file. Bolded relevant line which I changed to my package, however that isn't reflected when I run my program, it still says /jackpal/andtroidterm/Exec
    #include "common.h"
    
    #define LOG_TAG "Exec"
    
    #include <sys/types.h>
    #include <sys/ioctl.h>
    #include <sys/wait.h>
    #include <errno.h>
    #include <fcntl.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <termios.h>
    #include <signal.h>
    
    #include "termExec.h"
    
    static jclass class_fileDescriptor;
    static jfieldID field_fileDescriptor_descriptor;
    static jmethodID method_fileDescriptor_init;
    
    typedef unsigned short char16_t;
    
    class String8 {
    public:
        String8() {
            mString = 0;
        }
    
        ~String8() {
            if (mString) {
                free(mString);
            }
        }
    
        void set(const char16_t* o, size_t numChars) {
            if (mString) {
                free(mString);
            }
            mString = (char*) malloc(numChars + 1);
            if (!mString) {
                return;
            }
            for (size_t i = 0; i < numChars; i++) {
                mString[i] = (char) o[i];
            }
            mString[numChars] = '\0';
        }
    
        const char* string() {
            return mString;
        }
    private:
        char* mString;
    };
    
    static int throwOutOfMemoryError(JNIEnv *env, const char *message)
    {
        jclass exClass;
        const char *className = "java/lang/OutOfMemoryError";
    
        exClass = env->FindClass(className);
        return env->ThrowNew(exClass, message);
    }
    
    static int create_subprocess(const char *cmd,
        char *const argv[], char *const envp[], int* pProcessId)
    {
        char *devname;
        int ptm;
        pid_t pid;
    
        ptm = open("/dev/ptmx", O_RDWR); // | O_NOCTTY);
        if(ptm < 0){
            LOGE("[ cannot open /dev/ptmx - %s ]\n",strerror(errno));
            return -1;
        }
        fcntl(ptm, F_SETFD, FD_CLOEXEC);
    
        if(grantpt(ptm) || unlockpt(ptm) ||
           ((devname = (char*) ptsname(ptm)) == 0)){
            LOGE("[ trouble with /dev/ptmx - %s ]\n", strerror(errno));
            return -1;
        }
    
        pid = fork();
        if(pid < 0) {
            LOGE("- fork failed: %s -\n", strerror(errno));
            return -1;
        }
    
        if(pid == 0){
            close(ptm);
    
            int pts;
    
            setsid();
    
            pts = open(devname, O_RDWR);
            if(pts < 0) exit(-1);
    
            dup2(pts, 0);
            dup2(pts, 1);
            dup2(pts, 2);
    
            if (envp) {
                for (; *envp; ++envp) {
                    putenv(*envp);
                }
            }
    
            execv(cmd, argv);
            exit(-1);
        } else {
            *pProcessId = (int) pid;
            return ptm;
        }
    }
    
    
    static jobject android_os_Exec_createSubProcess(JNIEnv *env, jobject clazz,
        jstring cmd, jobjectArray args, jobjectArray envVars,
        jintArray processIdArray)
    {
        const jchar* str = cmd ? env->GetStringCritical(cmd, 0) : 0;
        String8 cmd_8;
        if (str) {
            cmd_8.set(str, env->GetStringLength(cmd));
            env->ReleaseStringCritical(cmd, str);
        }
    
        jsize size = args ? env->GetArrayLength(args) : 0;
        char **argv = NULL;
        String8 tmp_8;
        if (size > 0) {
            argv = (char **)malloc((size+1)*sizeof(char *));
            if (!argv) {
                throwOutOfMemoryError(env, "Couldn't allocate argv array");
                return NULL;
            }
            for (int i = 0; i < size; ++i) {
                jstring arg = reinterpret_cast<jstring>(env->GetObjectArrayElement(args, i));
                str = env->GetStringCritical(arg, 0);
                if (!str) {
                    throwOutOfMemoryError(env, "Couldn't get argument from array");
                    return NULL;
                }
                tmp_8.set(str, env->GetStringLength(arg));
                env->ReleaseStringCritical(arg, str);
                argv[i] = strdup(tmp_8.string());
            }
            argv[size] = NULL;
        }
    
        size = envVars ? env->GetArrayLength(envVars) : 0;
        char **envp = NULL;
        if (size > 0) {
            envp = (char **)malloc((size+1)*sizeof(char *));
            if (!envp) {
                throwOutOfMemoryError(env, "Couldn't allocate envp array");
                return NULL;
            }
            for (int i = 0; i < size; ++i) {
                jstring var = reinterpret_cast<jstring>(env->GetObjectArrayElement(envVars, i));
                str = env->GetStringCritical(var, 0);
                if (!str) {
                    throwOutOfMemoryError(env, "Couldn't get env var from array");
                    return NULL;
                }
                tmp_8.set(str, env->GetStringLength(var));
                env->ReleaseStringCritical(var, str);
                envp[i] = strdup(tmp_8.string());
            }
            envp[size] = NULL;
        }
    
        int procId;
        int ptm = create_subprocess(cmd_8.string(), argv, envp, &procId);
    
        if (argv) {
            for (char **tmp = argv; *tmp; ++tmp) {
                free(*tmp);
            }
            free(argv);
        }
        if (envp) {
            for (char **tmp = envp; *tmp; ++tmp) {
                free(*tmp);
            }
            free(envp);
        }
    
        if (processIdArray) {
            int procIdLen = env->GetArrayLength(processIdArray);
            if (procIdLen > 0) {
                jboolean isCopy;
    
                int* pProcId = (int*) env->GetPrimitiveArrayCritical(processIdArray, &isCopy);
                if (pProcId) {
                    *pProcId = procId;
                    env->ReleasePrimitiveArrayCritical(processIdArray, pProcId, 0);
                }
            }
        }
    
        jobject result = env->NewObject(class_fileDescriptor, method_fileDescriptor_init);
    
        if (!result) {
            LOGE("Couldn't create a FileDescriptor.");
        }
        else {
            env->SetIntField(result, field_fileDescriptor_descriptor, ptm);
        }
    
        return result;
    }
    
    
    static void android_os_Exec_setPtyWindowSize(JNIEnv *env, jobject clazz,
        jobject fileDescriptor, jint row, jint col, jint xpixel, jint ypixel)
    {
        int fd;
        struct winsize sz;
    
        fd = env->GetIntField(fileDescriptor, field_fileDescriptor_descriptor);
    
        if (env->ExceptionOccurred() != NULL) {
            return;
        }
    
        sz.ws_row = row;
        sz.ws_col = col;
        sz.ws_xpixel = xpixel;
        sz.ws_ypixel = ypixel;
    
        ioctl(fd, TIOCSWINSZ, &sz);
    }
    
    static void android_os_Exec_setPtyUTF8Mode(JNIEnv *env, jobject clazz,
        jobject fileDescriptor, jboolean utf8Mode)
    {
        int fd;
        struct termios tios;
    
        fd = env->GetIntField(fileDescriptor, field_fileDescriptor_descriptor);
    
        if (env->ExceptionOccurred() != NULL) {
            return;
        }
    
        tcgetattr(fd, &tios);
        if (utf8Mode) {
            tios.c_iflag |= IUTF8;
        } else {
            tios.c_iflag &= ~IUTF8;
        }
        tcsetattr(fd, TCSANOW, &tios);
    }
    
    static int android_os_Exec_waitFor(JNIEnv *env, jobject clazz,
        jint procId) {
        int status;
        waitpid(procId, &status, 0);
        int result = 0;
        if (WIFEXITED(status)) {
            result = WEXITSTATUS(status);
        }
        return result;
    }
    
    static void android_os_Exec_close(JNIEnv *env, jobject clazz, jobject fileDescriptor)
    {
        int fd;
    
        fd = env->GetIntField(fileDescriptor, field_fileDescriptor_descriptor);
    
        if (env->ExceptionOccurred() != NULL) {
            return;
        }
    
        close(fd);
    }
    
    static void android_os_Exec_hangupProcessGroup(JNIEnv *env, jobject clazz,
        jint procId) {
        kill(-procId, SIGHUP);
    }
    
    
    static int register_FileDescriptor(JNIEnv *env)
    {
        jclass localRef_class_fileDescriptor = env->FindClass("java/io/FileDescriptor");
    
        if (localRef_class_fileDescriptor == NULL) {
            LOGE("Can't find class java/io/FileDescriptor");
            return -1;
        }
    
        class_fileDescriptor = (jclass) env->NewGlobalRef(localRef_class_fileDescriptor);
    
        env->DeleteLocalRef(localRef_class_fileDescriptor);
    
        if (class_fileDescriptor == NULL) {
            LOGE("Can't get global ref to class java/io/FileDescriptor");
            return -1;
        }
    
        field_fileDescriptor_descriptor = env->GetFieldID(class_fileDescriptor, "descriptor", "I");
    
        if (field_fileDescriptor_descriptor == NULL) {
            LOGE("Can't find FileDescriptor.descriptor");
            return -1;
        }
    
        method_fileDescriptor_init = env->GetMethodID(class_fileDescriptor, "<init>", "()V");
        if (method_fileDescriptor_init == NULL) {
            LOGE("Can't find FileDescriptor.init");
            return -1;
         }
         return 0;
    }
    
    [B]static const char *classPathName = "com/example/Exec";[/B]
    static JNINativeMethod method_table[] = {
        { "createSubprocess", "(Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;[I)Ljava/io/FileDescriptor;",
            (void*) android_os_Exec_createSubProcess },
        { "setPtyWindowSize", "(Ljava/io/FileDescriptor;IIII)V",
            (void*) android_os_Exec_setPtyWindowSize},
        { "setPtyUTF8Mode", "(Ljava/io/FileDescriptor;Z)V",
            (void*) android_os_Exec_setPtyUTF8Mode},
        { "waitFor", "(I)I",
            (void*) android_os_Exec_waitFor},
        { "close", "(Ljava/io/FileDescriptor;)V",
            (void*) android_os_Exec_close},
        { "hangupProcessGroup", "(I)V",
            (void*) android_os_Exec_hangupProcessGroup}
    };
    
    int init_Exec(JNIEnv *env) {
        if (register_FileDescriptor(env) < 0) {
            LOGE("Failed to register class java/io/FileDescriptor");
            return JNI_FALSE;
        }
    
        if (!registerNativeMethods(env, classPathName, method_table,
                     sizeof(method_table) / sizeof(method_table[0]))) {
            return JNI_FALSE;
        }
    
        return JNI_TRUE;
    }
    

    package com.example;
    
    import java.io.FileDescriptor;
    
    /**
     * Utility methods for creating and managing a subprocess.
     * <p>
     * Note: The native methods access a package-private
     * java.io.FileDescriptor field to get and set the raw Linux
     * file descriptor. This might break if the implementation of
     * java.io.FileDescriptor is changed.
     */
    
    public class Exec
    {
        static {
            System.loadLibrary("jackpal-androidterm4");
        }
    
        /**
         * Create a subprocess. Differs from java.lang.ProcessBuilder in
         * that a pty is used to communicate with the subprocess.
         * <p>
         * Callers are responsible for calling Exec.close() on the returned
         * file descriptor.
         *
         * @param cmd The command to execute
         * @param args An array of arguments to the command
         * @param envVars An array of strings of the form "VAR=value" to be added
         * to the environment of the process
         * @param processId A one-element array to which the process ID of the
         * started process will be written.
         * @return the file descriptor of the started process.
         *
         */
        public static native FileDescriptor createSubprocess(
            String cmd, String[] args, String[] envVars, int[] processId);
            
        /**
         * Set the widow size for a given pty. Allows programs
         * connected to the pty learn how large their screen is.
         */
        public static native void setPtyWindowSize(FileDescriptor fd,
           int row, int col, int xpixel, int ypixel);
    
        /**
         * Set or clear UTF-8 mode for a given pty.  Used by the terminal driver
         * to implement correct erase behavior in cooked mode (Linux >= 2.6.4).
         */
        public static native void setPtyUTF8Mode(FileDescriptor fd,
           boolean utf8Mode);
    
        /**
         * Causes the calling thread to wait for the process associated with the
         * receiver to finish executing.
         *
         * @return The exit value of the Process being waited on
         *
         */
        public static native int waitFor(int processId);
    
        /**
         * Close a given file descriptor.
         */
        public static native void close(FileDescriptor fd);
    
        /**
         * Send SIGHUP to a process group.
         */
        public static native void hangupProcessGroup(int processId);
    }
    


  • Moderators, Science, Health & Environment Moderators, Social & Fun Moderators, Society & Culture Moderators Posts: 60,119 Mod ✭✭✭✭Tar.Aldarion


    This is the output of creating the shared library, so it looks like it does just make those files and chanign the name should work?
    Compile++ thumb  : jackpal-androidterm4 <= common.cpp
    In file included from jni/common.h:38:0,
                     from jni/common.cpp:33:
    /home/paul/Downloads/android-ndk-r8b/platforms/android-14/arch-arm/usr/include/jni.h:592:13: note: the mangling of 'va_list' has changed in GCC 4.4
    Compile++ thumb  : jackpal-androidterm4 <= termExec.cpp
    In file included from jni/common.h:38:0,
                     from jni/termExec.cpp:33:
    /home/paul/Downloads/android-ndk-r8b/platforms/android-14/arch-arm/usr/include/jni.h:592:13: note: the mangling of 'va_list' has changed in GCC 4.4
    Compile++ thumb  : jackpal-androidterm4 <= fileCompat.cpp
    In file included from jni/common.h:38:0,
                     from jni/fileCompat.cpp:17:
    /home/paul/Downloads/android-ndk-r8b/platforms/android-14/arch-arm/usr/include/jni.h:592:13: note: the mangling of 'va_list' has changed in GCC 4.4
    StaticLibrary  : libstdc++.a
    SharedLibrary  : libjackpal-androidterm4.so
    Install        : libjackpal-androidterm4.so => libs/armeabi/libjackpal-androidterm4.so
    Compile++ mips   : jackpal-androidterm4 <= common.cpp
    Compile++ mips   : jackpal-androidterm4 <= termExec.cpp
    Compile++ mips   : jackpal-androidterm4 <= fileCompat.cpp
    StaticLibrary  : libstdc++.a
    SharedLibrary  : libjackpal-androidterm4.so
    Install        : libjackpal-androidterm4.so => libs/mips/libjackpal-androidterm4.so
    Compile++ x86    : jackpal-androidterm4 <= common.cpp
    Compile++ x86    : jackpal-androidterm4 <= termExec.cpp
    Compile++ x86    : jackpal-androidterm4 <= fileCompat.cpp
    StaticLibrary  : libstdc++.a
    SharedLibrary  : libjackpal-androidterm4.so
    Install        : libjackpal-androidterm4.so => libs/x86/libjackpal-androidterm4.so
    
    


  • Registered Users, Registered Users 2 Posts: 18,272 ✭✭✭✭Atomic Pineapple


    Are the files that bind the JNI matching correctly?

    For example say I have the follwoing .h file:

    com_draffodx_jni_Example

    The equivalent java file is called Example.java and has the package name, com.draffodx.jni

    Are these correct in your project?


  • Moderators, Science, Health & Environment Moderators, Social & Fun Moderators, Society & Culture Moderators Posts: 60,119 Mod ✭✭✭✭Tar.Aldarion


    I'm not sure if they are right, taking your example: The .h is just called example.h, the java file is a different name, and has a package. However in the .cpp files there is a class path called com/something/Example and it all works fine unless I change the package name. I'll try messing around with the names cheers.


    I think I'll just have to delete everything and start over. The best bit is where I deleted all the copies of the shared library, but the original program still runs... which was dependent on it.
    The ole reinstall soon for me.


Advertisement