Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie

Changing package name breaks app?

Options
  • 19-11-2012 4:33pm
    #1
    Moderators, Science, Health & Environment Moderators, Social & Fun Moderators, Society & Culture Moderators Posts: 60,097 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 Posts: 18,272 ✭✭✭✭Atomic Pineapple


    Which package name are you changing?


  • Moderators, Science, Health & Environment Moderators, Social & Fun Moderators, Society & Culture Moderators Posts: 60,097 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 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,097 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 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,097 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 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,097 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,097 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 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,097 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,097 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 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,097 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,097 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 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,097 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