Skip to content
This repository has been archived by the owner on Jul 3, 2020. It is now read-only.

What to replace arm-linux-androideabi with in manifest? #234

Closed
OptimisticPeach opened this issue Aug 31, 2019 · 20 comments
Closed

What to replace arm-linux-androideabi with in manifest? #234

OptimisticPeach opened this issue Aug 31, 2019 · 20 comments

Comments

@OptimisticPeach
Copy link
Contributor

I'm trying to get a project to compile that previously (About 6 months ago) compiled, I get the following error when I try to compile it as is:

error: unknown variant `arm-linux-androideabi`, expected one of `armv7-linux-androideabi`, `aarch64-linux-android`, `i686-linux-android`, `x86_64-linux-android` for key `package.metadata.android.build_targets` at line 51 column 1

So, I try armv7-linux-androideabi, which successfully compiles and installs through adb, but fails to launch. I'm trying to run this on a Pixel 2, where I used to use arm-linux-androideabi, cpu-z reports the kernel arch is aarch64 (Which apparently doesn't work) and the closest I could find was armv7-linux-androideabi (Which doesn't work either).

In PR #223 I read the following:

  • The default and supported build targets has changed. The default is to build on all targets supported by the current NDK. arm-linux-androideabi was removed. See README for supported targets.

How might I go about making my app compile and run on my Pixel 2?

On a side note, I used to clone cargo-apk locally and edit the NativeActivity code to remove the decoration and navigation bars (It's kind of difficult to play snake with them), where might I inject that code now? "Injected"/"replaced" code is here.

@OptimisticPeach
Copy link
Contributor Author

Here is the adb logcat dump of compiling a "default" project with this (The only different thing about the default manifest is that I've changed the name and don't ask for the camera)

@philip-alldredge
Copy link
Contributor

The appropriate ABI is "aarch64-linux-android". What do you mean when you say it doesn't work? Does it fail to build or fail to run? Is there an error?

The fullscreen option in your cargo manifest will set the theme so that the status bar will be removed. However, the navigation bars will still be there. I'm not sure of a way to hide the navigation bars at the moment. Long term there should be an API provided.

There may be a way to call the appropriate functions using JNI and include them in the rust portion in android_native_app_glue.c but I don't have experience in that area.

@philip-alldredge
Copy link
Contributor

What NDK and SDK are you using? I don't have a pixel 2 but I haven't had any problems running the examples on the emulator, ARM7, or ARM64 devices. Any warnings or errors when building?

@OptimisticPeach
Copy link
Contributor Author

OptimisticPeach commented Aug 31, 2019

What do you mean when you say it doesn't work? Does it fail to build or fail to run? Is there an
error?

It fails to run, with the logcat errors produced. It will try to "flash open" expanding from the app icon, and then it will simply go back to the home screen (Or the app drawer).

There may be a way to call the appropriate functions using JNI and include them in the rust portion in android_native_app_glue.c but I don't have experience in that area.

I tried that some time ago, when originally making the app, but I found that it is illegal to call said functions in the native activity thread, therefore forcing me to run them in the NativeActivity code, which runs in the main thread.

What NDK and SDK are you using?

PS P:\sdk\tools\bin> .\sdkmanager.bat --list
Installed packages:
  Path                                                | Version      | Description                                     | Location
  -------                                             | -------      | -------                                         | -------
  build-tools;27.0.3                                  | 27.0.3       | Android SDK Build-Tools 27.0.3                  | build-tools\27.0.3\
  build-tools;28.0.3                                  | 28.0.3       | Android SDK Build-Tools 28.0.3                  | build-tools\28.0.3\
  build-tools;29.0.2                                  | 29.0.2       | Android SDK Build-Tools 29.0.2                  | build-tools\29.0.2\
  emulator                                            | 27.3.10      | Android Emulator                                | emulator\
  extras;android;m2repository                         | 47.0.0       | Android Support Repository                      | extras\android\m2repository\
  extras;google;m2repository                          | 58           | Google Repository                               | extras\google\m2repository\
  extras;intel;Hardware_Accelerated_Execution_Manager | 7.3.2        | Intel x86 Emulator Accelerator (HAXM installer) | extras\intel\Hardware_Accelerated_Execution_Manager\
  ndk-bundle                                          | 20.0.5594570 | NDK                                             | ndk-bundle\
  ndk;20.0.5594570                                    | 20.0.5594570 | NDK (Side by side) 20.0.5594570                 | ndk\20.0.5594570\
  patcher;v4                                          | 1            | SDK Patch Applier v4                            | patcher\v4\
  platform-tools                                      | 29.0.2       | Android SDK Platform-Tools                      | platform-tools\
  platforms;android-18                                | 3            | Android SDK Platform 18                         | platforms\android-18\
  platforms;android-25                                | 3            | Android SDK Platform 25                         | platforms\android-25\
  platforms;android-26                                | 2            | Android SDK Platform 26                         | platforms\android-26\
  platforms;android-27                                | 3            | Android SDK Platform 27                         | platforms\android-27\
  platforms;android-28                                | 6            | Android SDK Platform 28                         | platforms\android-28\
  platforms;android-29                                | 3            | Android SDK Platform 29                         | platforms\android-29\
  sources;android-18                                  | 1            | Sources for Android 18                          | sources\android-18\
  sources;android-25                                  | 1            | Sources for Android 25                          | sources\android-25\
  sources;android-26                                  | 1            | Sources for Android 26                          | sources\android-26\
  sources;android-27                                  | 1            | Sources for Android 27                          | sources\android-27\
  system-images;android-18;default;x86                | 3            | Intel x86 Atom System Image                     | system-images\android-18\default\x86\
  system-images;android-18;google_apis;armeabi-v7a    | 5            | Google APIs ARM EABI v7a System Image           | system-images\android-18\google_apis\armeabi-v7a\
  system-images;android-25;google_apis;x86            | 15           | Google APIs Intel x86 Atom System Image         | system-images\android-25\google_apis\x86\
  system-images;android-27;google_apis;x86            | 8            | Google APIs Intel x86 Atom System Image         | system-images\android-27\google_apis\x86\
  tools                                               | 26.1.1       | Android SDK Tools                               | tools\

I installed the Android-29 packages, but then realized that the Pixel 2 runs on api level 28, so there was no point.

Any warnings or errors when building?

PS Z:\android\doze_widget\doze_widget> cargo apk build
Compiling injected-glue for aarch64-linux-android
warning: use of deprecated item 'std::mem::uninitialized': use `mem::MaybeUninit` instead
   --> Z:\android\doze_widget\doze_widget\target\android-artifacts\debug\injected-glue\lib.rs:298:30
    |
298 |             let mut thread = mem::uninitialized();
    |                              ^^^^^^^^^^^^^^^^^^
    |
    = note: `#[warn(deprecated)]` on by default

warning: use of deprecated item 'std::mem::uninitialized': use `mem::MaybeUninit` instead
   --> Z:\android\doze_widget\doze_widget\target\android-artifacts\debug\injected-glue\lib.rs:347:30
    |
347 |             let mut events = mem::uninitialized();
    |                              ^^^^^^^^^^^^^^^^^^

warning: use of deprecated item 'std::mem::uninitialized': use `mem::MaybeUninit` instead
   --> Z:\android\doze_widget\doze_widget\target\android-artifacts\debug\injected-glue\lib.rs:348:61
    |
348 |             let mut source: *mut ffi::android_poll_source = mem::uninitialized();
    |                                                             ^^^^^^^^^^^^^^^^^^

   Compiling doze_widget v0.1.0 (Z:\android\doze_widget\doze_widget)
    Finished dev [unoptimized + debuginfo] target(s) in 2.04s
aapt2.exe W 08-31 18:14:02 10756  5924 ApkAssets.cpp:138] resources.arsc in APK 'P:\sdk\platforms\android-29\android.jar' is compressed.
 'lib/arm64-v8a/libdoze_widget.so'...
Verifying alignment of Z:\android\doze_widget\doze_widget\target\android-artifacts\debug\apk\doze_widget.apk (4)...
      49 AndroidManifest.xml (OK - compressed)
    1248 res/mipmap-mdpi-v4/ic_launcher.png (OK)
    3272 res/mipmap-hdpi-v4/ic_launcher.png (OK)
    6496 res/mipmap-xhdpi-v4/ic_launcher.png (OK)
   10616 res/mipmap-xxhdpi-v4/ic_launcher.png (OK)
   16716 res/mipmap-xxxhdpi-v4/ic_launcher.png (OK)
   25072 resources.arsc (OK)
   26303 assets/fonts\Ubuntu-R.ttf (OK - compressed)
  198688 lib/arm64-v8a/libdoze_widget.so (OK - compressed)
Verification succesful
PS Z:\android\doze_widget\doze_widget> adb install --abi arm64-v8a .\target\android-artifacts\debug\apk\doze_widget.apk
Performing Streamed Install
Success

Those are mostly code-etiquette things, so they shouldn't really do much (Unless you're doing something wrong with uninitialized memory which would explain this).

I use adb install --abi arm64-v8a <PATH> to install directly to make sure I have the right abi.

@OptimisticPeach
Copy link
Contributor Author

I tried with both nightly-x86_64-pc-windows-gnu and nightly-x86_64-pc-windows-msvc toolchains, with the appropriate targets installed.

@philip-alldredge
Copy link
Contributor

Would you mind posting a non-functional APK? I have been unable to reproduce so far. Either that or checking the binary to see if the ANativeActivity_onCreate or similar symbol is appearing in the binary.

@philip-alldredge
Copy link
Contributor

Do you happen to be building a release build? We are stripping symbols and that seems to be causing the problem. We won't need to strip all symbols.

@OptimisticPeach
Copy link
Contributor Author

doze_widget.zip
This app is defined with the following main.rs:

fn main() {
    
}

And the following manifest:

[package]
name = "doze_widget"
version = "0.1.0"
authors = ["OptimisticPeach <optimistic.peach@outlook.com>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]


[package.metadata.android]
# The target Android API level.
# "android_version" is the compile SDK version. It defaults to 29.
# (target_sdk_version defaults to the value of "android_version")
# (min_sdk_version defaults to 18) It defaults to 18 because this is the minimum supported by rustc.
android_version = 29
target_sdk_version = 29
min_sdk_version = 26

# Specifies the array of targets to build for.
# Defaults to "armv7-linux-androideabi", "aarch64-linux-android", "i686-linux-android".
build_targets = [ "aarch64-linux-android" ]

#
# The following value can be customized on a per bin/example basis. See multiple_targets example
# If a value is not specified for a secondary target, it will inherit the value defined in the `package.metadata.android`
# section unless otherwise noted.
#

# The Java package name for your application.
# Hyphens are converted to underscores.
# Defaults to rust.<target_name> for binaries. 
# Defaults to rust.<package_name>.example.<target_name> for examples.
# For example: for a binary "my_app", the default package name will be "rust.my_app"
# Secondary targets will not inherit the value defined in the root android configuration.
# package_name = "rust.cargo.apk.advanced"

# The user-friendly name for your app, as displayed in the applications menu.
# Defaults to the target name
# Secondary targets will not inherit the value defined in the root android configuration.
label = "DozeWidget"

# Internal version number used to determine whether one version is more recent than another. Must be an integer.
# Defaults to 1
# See https://developer.android.com/guide/topics/manifest/manifest-element
version_code = 1

# The version number shown to users.
# Defaults to the cargo package version number
# See https://developer.android.com/guide/topics/manifest/manifest-element
version_name = "1.0"

# Path to your application's resources folder.
# If not specified, resources will not be included in the APK
res = "./res"

# Virtual path your application's icon for any mipmap level.
# If not specified, an icon will not be included in the APK.
icon = "@mipmap/ic_launcher"

# Path to the folder containing your application's assets.
# If not specified, assets will not be included in the APK
assets = "./assets"

# If set to true, makes the app run in full-screen, by adding the following line
# as an XML attribute to the manifest's <application> tag :
#     android:theme="@android:style/Theme.DeviceDefault.NoActionBar.Fullscreen
# Defaults to false.
fullscreen = false

# The maximum supported OpenGL ES version , as claimed by the manifest.
# Defaults to 2.0.
# See https://developer.android.com/guide/topics/graphics/opengl.html#manifest
opengles_version_major = 3
opengles_version_minor = 2

# Adds extra arbitrary XML attributes to the <application> tag in the manifest.
# See https://developer.android.com/guide/topics/manifest/application-element.html
[package.metadata.android.application_attributes]
"android:debuggable" = "true"
"android:hardwareAccelerated" = "true"

# Adds extra arbitrary XML attributes to the <activity> tag in the manifest.
# See https://developer.android.com/guide/topics/manifest/activity-element.html
[package.metadata.android.activity_attributes]
"android:screenOrientation" = "unspecified"
"android:uiOptions" = "none"

# Adds a uses-feature element to the manifest
# Supported keys: name, required, version
# The glEsVersion attribute is not supported using this section. 
# It can be specified using the opengles_version_major and opengles_version_minor values
# See https://developer.android.com/guide/topics/manifest/uses-feature-element
# [[package.metadata.android.feature]]
#name = "android.software.app_widgets"
#name = ""

[[package.metadata.android.feature]]
name = "android.hardware.vulkan.level"
version = "1"
required = false

# Adds a uses-permission element to the manifest.
# Note that android_version 23 and higher, Android requires the application to request permissions at runtime.
# There is currently no way to do this using a pure NDK based application.
# See https://developer.android.com/guide/topics/manifest/uses-permission-element
[[package.metadata.android.permission]]
name = "android.permission.WRITE_EXTERNAL_STORAGE"
max_sdk_version = 18

[[package.metadata.android.permission]]
name = "android.permission.CAMERA"

End of manifest

I'm not using release mode currently, and using it produces the same result.

@OptimisticPeach
Copy link
Contributor Author

doze_widget.zip
Here's a version (Still debug like the last) which has default targets enables in case you needed that.

@philip-alldredge
Copy link
Contributor

Are you using rust 1.37.0. I wasn't able to reproduce your issue. I just upgraded and now I have the same results.

@mb64 what version of rust are you using when you started encountered your symbol issue?

@OptimisticPeach
Copy link
Contributor Author

OptimisticPeach commented Sep 1, 2019

PS Z:\android\doze_widget\doze_widget> rustup default
nightly-x86_64-pc-windows-msvc (default)
PS Z:\android\doze_widget\doze_widget> rustc -V
rustc 1.39.0-nightly (4295eea90 2019-08-30)

I just updated today (And yesterday) for trying to get this to work.
I can try stable, give me a moment.

If I use

PS Z:\android\doze_widget\doze_widget> rustup default
stable-x86_64-pc-windows-msvc (default)
PS Z:\android\doze_widget\doze_widget> rustc -V
rustc 1.37.0 (eae3437df 2019-08-13)

(Which was updated just moments ago, and has the appropriate targets, etc, etc)
I still get the same error on logcat, and the same behavior on the phone.

@OptimisticPeach
Copy link
Contributor Author

Huzzah! You were right, using

PS Z:\android\doze_widget\doze_widget> rustup default
1.36.0-x86_64-pc-windows-msvc (default)
PS Z:\android\doze_widget\doze_widget> rustc -V
rustc 1.36.0 (a53f9df32 2019-07-03)

I get a working APK, so it seems that something in rust 1.37.0 broke the build process 😬

@philip-alldredge
Copy link
Contributor

Sorry, I wasn't clear. I was on 1.36 and it was working. 1.37 broke things for me.

I looked at the symbol table and on

1.36.0 ANativeActivity_onCreate is in both .symtab and .dynsym. On 1.37.0 it is only in .symtab. That would explain the issue.

@OptimisticPeach
Copy link
Contributor Author

OptimisticPeach commented Sep 1, 2019

I don't know what .symtab or .dynsym are, but I assume they have to do with the symbols given their name and what you've explained. Is there any clear way to fix this or am I is everyone forced to use rust 1.36.0?

@philip-alldredge
Copy link
Contributor

At the moment I don't know how to fix or work around the issue. The symbol isn't being exported from the shared object. For now everyone will need to use 1.36 until a solution is found.

@philip-alldredge
Copy link
Contributor

@OptimisticPeach

I don't know how to fix it properly but I thought of a temporary work around if you are willing to make some small mods to your version of cargo-apk.

Add to the bottom of injected-glue/lib.rs:

#[no_mangle]
#[inline(never)]
#[allow(non_snake_case)]
pub unsafe extern "C" fn ANativeActivity_onCreate(activity: *mut c_void, saved_state: *mut c_void, saved_state_size: usize) {
    ANativeActivity_onCreate2(activity, saved_state, saved_state_size);
}

extern {
    #[allow(non_snake_case)]
    fn ANativeActivity_onCreate2(activity: *mut c_void, saved_state: *mut c_void, saved_state_size: usize);
}

Near the bottom of native_app_glue/android_native_app_glue.c:

  • Rename ANativeActivity_onCreate to ANativeActivity_onCreate2

@mb64 do you have any thoughts on how to best fix this issue? I'm going to hold off on any potential pull requests until we decide how to best fix it. Ideally we would just specify a linker command or something to rexport the symbol but the above work around appears to work. very limited testing so far.

@philip-alldredge
Copy link
Contributor

@OptimisticPeach thanks for your help in tracking down the issue and bringing it to our attention. @mb64 had ran into it but I didn't realize it affected the master branch due to it being a compatibility issue with 1.37.0. I went ahead and pushed a branch with this and some additional fixes #237 . This solution may not be the final solution but you can just use that branch for now.

I'm not the maintainer but personally, I'd recommend starting a new issue for hiding the navigation bar so it isn't lost in the shuffle.

@philip-alldredge
Copy link
Contributor

philip-alldredge commented Sep 1, 2019

@OptimisticPeach

One last note. I did some playing with hiding the navigation bar. It's possible without Java code. You'll need to modify native_app_glue/native_app_glue.c.

It should be possible to do this from rust, using the jni crate and the current android glue, but I'm not going to invest the time in doing that right now. @mb64 has been working on refactoring some of this to move it out of cargo-apk. Once that is done it'll be easier to add an API to do this from rust. We'll have to consider the threading issues that you mentioned. The code below requires uses the JNIEnv of the native activity thread as opposed to getting a new one. This is okay in this case since it the JNIEnv provided by ANativeActivity is the correct one for the native activity callbacks.

Since you were modifying cargo-apk anyways, you should be in the same state as you were before.

Please note that there may be compatibility issues if using the android_glue crate from crates.io with the master cargo-apk. I ran into that a while back when using it.

Replace onWindowFocusChanged with the following code:

static void hide_navigation_bar(ANativeActivity* activity)
{
    // If this function was called from another thread, the activity->vm field would need to be used to attach a thread to get a valid JNIEnv*
    JNIEnv* env = activity->env;

    jclass activityClass = (*env)->FindClass(env, "android/app/NativeActivity");
    jmethodID getWindow = (*env)->GetMethodID(env, activityClass, "getWindow", "()Landroid/view/Window;");

    jclass windowClass = (*env)->FindClass(env, "android/view/Window");
    jmethodID getDecorView = (*env)->GetMethodID(env, windowClass, "getDecorView", "()Landroid/view/View;");

    jclass viewClass = (*env)->FindClass(env, "android/view/View");
    jmethodID setSystemUiVisibility = (*env)->GetMethodID(env, viewClass, "setSystemUiVisibility", "(I)V");

    jobject window = (*env)->CallObjectMethod(env, activity->clazz, getWindow);

    jobject decorView = (*env)->CallObjectMethod(env, window, getDecorView);

    jfieldID flagFullscreenID = (*env)->GetStaticFieldID(env, viewClass, "SYSTEM_UI_FLAG_FULLSCREEN", "I");
    jfieldID flagHideNavigationID = (*env)->GetStaticFieldID(env, viewClass, "SYSTEM_UI_FLAG_HIDE_NAVIGATION", "I");
    jfieldID flagImmersiveStickyID = (*env)->GetStaticFieldID(env, viewClass, "SYSTEM_UI_FLAG_IMMERSIVE_STICKY", "I");

    const int flagFullscreen = (*env)->GetStaticIntField(env, viewClass, flagFullscreenID);
    const int flagHideNavigation = (*env)->GetStaticIntField(env, viewClass, flagHideNavigationID);
    const int flagImmersiveSticky = (*env)->GetStaticIntField(env, viewClass, flagImmersiveStickyID);
    const int flag = flagFullscreen | flagHideNavigation | flagImmersiveSticky;

    (*env)->CallVoidMethod(env, decorView, setSystemUiVisibility, flag);
}

static void onWindowFocusChanged(ANativeActivity* activity, int focused) {
    LOGV("WindowFocusChanged: %p -- %d\n", activity, focused);
    android_app_write_cmd((struct android_app*)activity->instance,
            focused ? APP_CMD_GAINED_FOCUS : APP_CMD_LOST_FOCUS);
    hide_navigation_bar(activity);
}

The code is modified from https://stackoverflow.com/a/50831255

@OptimisticPeach
Copy link
Contributor Author

That sounds perfect! I will definitely use this, and thanks for all the help on doing this!

I'm going to close this issue and instead make another issue dedicated to android startup things and an android api (Which would be capable of this) that run on the main thread.

@OptimisticPeach
Copy link
Contributor Author

I'm also deferring the ANativeActivity_onCreate error to #235 because it is more appropriately named.

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