Search code examples
javaandroidc++java-native-interfacecross-platform

Native/C++/Java Android NDK/JNI - Sharing Native Code Among Activities (MSDN hello-jni Sample Modification)


I'm new to Android development and decided to try the MSDN's sample solution called hello-jni located here:

https://code.msdn.microsoft.com/hello-jni-android-790ab73d

Opening the sample without modifications and running from Visual Studio 2015 Community works fine. I'm running on my LG L16C cheapo android phone (Android 4.4.2, compiling against Android 19) for all my testing.

I've been able to create an additional activity, with its own layout, without a problem despite the "R" identifier not showing up in the Intellisense. The sample has a native-code method, called from Java, which returns a string and is utilized in the "main activity", HelloJNI java-class. This also all works without any problems.

However, when I try to use the same code (native c++ and java code to call the native code) in another activity class, it fails. I also duplicated each step I tried in Android Studio that was done in Visual Studio, duplicating the hello-jni sample for comparison purposes, and I get the same results there - whenever the second activity tries to use any native code, the app just crashes.

Any suggestions what I might be doing wrong here?

If you download the sample as-is and then add the following changes, you can reproduce the problem:

AnotherActivity.java:

package com.miahcode.hellojni;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

public class AnotherActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
		TextView tv = new TextView(this);
		tv.setText( stringFromJNI() );
        setContentView(tv);
    }

	public native String stringFromJNI();

	static {
        System.loadLibrary("hello-jni");
    }
}

AndriodManifest.xml:

    <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.miahcode.hellojni"
      android:versionCode="1"
      android:versionName="1.0">
  <uses-sdk android:minSdkVersion="3" />
  <application android:label="@string/app_name"
               android:debuggable="true">
    <activity android:name=".HelloJni"
              android:label="@string/app_name">
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
    </activity>
    <activity android:name=".AnotherActivity"></activity>
  </application>
</manifest>

Here is the hello-jni.c that harbors the native code:

/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
#include <string.h>
#include <jni.h>

/* This is a trivial JNI miahcode where we use a native method
 * to return a new VM String. See the corresponding Java source
 * file located at:
 *
 *   apps/samples/hello-jni/project/src/com/miahcode/hellojni/HelloJni.java
 */
jstring Java_com_miahcode_hellojni_HelloJni_stringFromJNI( JNIEnv* env, jobject thiz )
{
#if defined(__arm__)
  #if defined(__ARM_ARCH_7A__)
    #if defined(__ARM_NEON__)
      #if defined(__ARM_PCS_VFP)
        #define ABI "armeabi-v7a/NEON (hard-float)"
      #else
        #define ABI "armeabi-v7a/NEON"
      #endif
    #else
      #if defined(__ARM_PCS_VFP)
        #define ABI "armeabi-v7a (hard-float)"
      #else
        #define ABI "armeabi-v7a"
      #endif
    #endif
  #else
   #define ABI "armeabi"
  #endif
#elif defined(__i386__)
   #define ABI "x86"
#elif defined(__x86_64__)
   #define ABI "x86_64"
#elif defined(__mips64)  /* mips64el-* toolchain defines __mips__ too */
   #define ABI "mips64"
#elif defined(__mips__)
   #define ABI "mips"
#elif defined(__aarch64__)
   #define ABI "arm64-v8a"
#else
   #define ABI "unknown"
#endif

    return (*env)->NewStringUTF(env, "Compiled with ABI " ABI ".");
}

Thanks, J


Solution

  • You need to post your native C code or the error log so I can't be sure- but my bet is you didn't change it to have the correct function name, so it can't find a match for the native function. Notice the name of the function: Java_com_example_hellojni_HelloJni_stringFromJNI. To match, the name needs to be Java_your_package_name_with_underscore_for_period_classname_functionname.