I am trying to load two shared libraries in my Android application through the loadLibrary call:
System.loadLibrary("mywrapper");
System.loadLibrary("crypto");
I keep running catching the `UnsatisfiedLinkError. Here is a more detailed version of the error.
Caused by: java.lang.UnsatisfiedLinkError: Cannot load library: link_image[1969]:
130 could not load needed library 'libcrypto.so.1.0.0' for
'libmywrapper.so' (load_library[1111]: Library 'libcrypto.so.1.0.0' not found)
Any ideas?
After spending some time I found out that Android doesn't support versioned libraries. Has any one faced the same issue?
I had the same problem on building libwebsockets for Android, which needs to link with OpenSSL. I use libssl.so as example. You should do the same for related .so files.
Before:
huiying#huiying-PORTEGE-R835:~$ objdump -p libssl.so | grep so
libssl.so: file format elf32-little
NEEDED libcrypto.so.1.0.0
NEEDED libdl.so
NEEDED libc.so
SONAME libssl.so.1.0.0
After
huiying#huiying-PORTEGE-R835:~$ rpl -R -e .so.1.0.0 "_1_0_0.so" libssl.so
Replacing ".so.1.0.0" with "_1_0_0.so" (case sensitive) (partial words matched)
.
A Total of 2 matches replaced in 1 file searched.
huiying#huiying-PORTEGE-R835:~$ objdump -p libssl.so | grep so
libssl.so: file format elf32-little
NEEDED libcrypto_1_0_0.so
NEEDED libdl.so
NEEDED libc.so
SONAME libssl_1_0_0.so
And don't forget to change file name "libssl.so" to "libssl_1_0_0.so".
The hack works. I have running Android app to prove it. See my rant at http://computervisionandjava.blogspot.com/2015/05/trouble-with-versioned-shared-libraries.html.
It seems android has an issue with loading versioned libraries.The issue at hand was because of library so-name in my case libcrypto.so.1.0.0. Even if you rename the library and try to load it as a prebuilt shared library in an android make file it fails.( It has to be because the library name is somehow embedded in the file. And any library that links with it expects to be linked with a library of with the same name )
I hope there are other ways out there when it comes to handling libraries with version names in android.
For now I am evading the problem all together by using static libraries of openssl and linking them with my own shared library.
Year 2014 and still no support for versioned shared libs. So I made a script to patch SONAME. Just point the script to input dir where all versioned libs placed. Then check output dir "unver".
#!/bin/bash
DIR="$1"
if [ "$DIR" == "" ]; then
echo "Usage: fix-soname.sh <target dir>"
exit
fi
if [ ! -d $DIR ]; then
echo "Not found: $DIR"
exit
fi
OUT="$DIR/unver"
echo "Input=$DIR"
echo "Output=$OUT"
CWD=$(pwd)
cd $DIR
# prep dirs
mkdir -p $OUT
rm -f -R $OUT/*
# rename libs and copy to out dir
find "$DIR" -type f -name '*.so*' | while read FILE; do
NAME=$(basename "$FILE")
SONAME=$NAME
while read SYMLINK; do
X=$(basename "$SYMLINK")
#echo "$X (${#X}) -> $NAME (${#NAME})"
if [ "${#X}" -lt "${#SONAME}" ]; then
SONAME=$X
fi
done<<EOT
`find -L $DIR -samefile $FILE`
EOT
#echo $SONAME
cp -f $SONAME $OUT/
done
# patch libs in out dir
find "$OUT" -type f -name '*.so*' | while read FILE; do
# get file name without path
NAME=$(basename "$FILE")
# extract SONAME from shared lib
SONAME=`readelf -d $FILE | grep '(SONAME)' | grep -P '(?<=\[)(lib.*?)(?=\])' -o`
#echo "$NAME [$SONAME]"
# patch SONAME if required
if [ "$NAME" != "$SONAME" ]; then
L1=${#NAME}
L2=${#SONAME}
LDIFF=$((L2-L1))
#echo "$NAME [$SONAME] ($LDIFF)"
if [ "$LDIFF" -gt "0" ]; then
SONEW=$NAME
for (( c=1; c<=$LDIFF; c++ )); do
SONEW+="\x00"
done
echo "$NAME [$SONAME] -> $SONEW ($LDIFF)"
rpl -R -e "$SONAME" "$SONEW" $OUT
fi
fi
done
cd $CWD
Related
I am trying to flash Android Q User-debug build into my Pixel2 XL device from my mac pc but its getting failed with the below error message.
[ 27% 31880/114806] Copy non-ELF: out/target/product/taimen/system/lib/lib-imsv
FAILED: out/target/product/taimen/system/lib/lib-imsvideocodec.so
/bin/bash -c "(if prebuilts/clang/host/darwin-x86/clang-r383902/bin/llvm-readobj -h vendor/qcom/taimen/proprietary/lib-imsvideocodec.so >/dev/null 2>&1; then echo -e \"\\033[1mout/target/product/taimen/system/lib/lib-imsvideocodec.so: \\033[31merror:\\033[0m\\033[1m\" 'found ELF prebuilt in PRODUCT_COPY_FILES, use cc_prebuilt_binary / cc_prebuilt_library_shared instead.' \"\\033[0m\" >&2; echo -e \"\\033[1mout/target/product/taimen/system/lib/lib-imsvideocodec.so: \\033[31merror:\\033[0m\\033[1m\" 'found ELF file: vendor/qcom/taimen/proprietary/lib-imsvideocodec.so' \"\\033[0m\" >&2; false; fi ) && (mkdir -p out/target/product/taimen/system/lib/ ) && (rm -f out/target/product/taimen/system/lib/lib-imsvideocodec.so ) && (cp \"vendor/qcom/taimen/proprietary/lib-imsvideocodec.so\" \"out/target/product/taimen/system/lib/lib-imsvideocodec.so\" )"
out/target/product/taimen/system/lib/lib-imsvideocodec.so: error: found ELF prebuilt in PRODUCT_COPY_FILES, use cc_prebuilt_binary / cc_prebuilt_library_shared instead.
out/target/product/taimen/system/lib/lib-imsvideocodec.so: error: found ELF file: vendor/qcom/taimen/proprietary/lib-imsvideocodec.so
[ 27% 31881/114806] Copy non-ELF: out/target/product/taimen/system/lib/lib-imsv
FAILED: out/target/product/taimen/system/lib/lib-imsvtextutils.so
/bin/bash -c "(if prebuilts/clang/host/darwin-x86/clang-r383902/bin/llvm-readobj -h vendor/qcom/taimen/proprietary/lib-imsvtextutils.so >/dev/null 2>&1; then echo -e \"\\033[1mout/target/product/taimen/system/lib/lib-imsvtextutils.so: \\033[31merror:\\033[0m\\033[1m\" 'found ELF prebuilt in PRODUCT_COPY_FILES, use cc_prebuilt_binary / cc_prebuilt_library_shared instead.' \"\\033[0m\" >&2; echo -e \"\\033[1mout/target/product/taimen/system/lib/lib-imsvtextutils.so: \\033[31merror:\\033[0m\\033[1m\" 'found ELF file: vendor/qcom/taimen/proprietary/lib-imsvtextutils.so' \"\\033[0m\" >&2; false; fi ) && (mkdir -p out/target/product/taimen/system/lib/ ) && (rm -f out/target/product/taimen/system/lib/lib-imsvtextutils.so ) && (cp \"vendor/qcom/taimen/proprietary/lib-imsvtextutils.so\" \"out/target/product/taimen/system/lib/lib-imsvtextutils.so\" )"
out/target/product/taimen/system/lib/lib-imsvtextutils.so: error: found ELF prebuilt in PRODUCT_COPY_FILES, use cc_prebuilt_binary / cc_prebuilt_library_shared instead.
out/target/product/taimen/system/lib/lib-imsvtextutils.so: error: found ELF file: vendor/qcom/taimen/proprietary/lib-imsvtextutils.so
22:34:16 ninja failed with: exit status 1
Below is my build steps :
mkdir ~/bin
export PATH=~/bin:$PATH
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo
repo init -u https://android.googlesource.com/platform/manifest -b master
repo sync -c -j4
wget https://dl.google.com/dl/android/aosp/google_devices-taimen-qq1a.191205.008-f4537f93.tgz
tar xvf google_devices-taimen-qq1a.191205.008-f4537f93.tgz
./extract-google_devices-taimen.sh
wget https://dl.google.com/dl/android/aosp/qcom-taimen-qq1a.191205.008-760afa6e.tgz
tar xvf qcom-taimen-qq1a.191205.008-760afa6e.tgz
./extract-qcom-taimen.sh
. build/envsetup.sh
lunch aosp_taimen-userdebug
m
Since for the first time I am building the AOSP I couldn't understand the error found ELF prebuilt in PRODUCT_COPY_FILES, use cc_prebuilt_binary / cc_prebuilt_library_shared instead.
Please advise me what to do. Thank you.
This Issue Link might be helpful for you to read.
For your issue, I believe it's related to the device binary you download.
Try to download the newest, which is listed at the bottom, for you pixel 2 XL.
Redo the extract*.sh part and make again!
I got the same error.
yes, we can add this flag to BoardConfig.mk, but it is not a clean solution since Google encourages the use of Android.bp files instead of Makefiles. Thant's what the soong suggested the use of these modules (cc_prebuilt_binary / cc_prebuilt_library_shared).
In my case, solved this problem by creating Android.bp file in the repo where I put my prebuilt libraries, then I added them as product packages in the product mk file. this is an example :
Android.bp :
cc_prebuilt_library {
name: "product_package_name_in_MK_file",
relative_install_path: "sub_lib/sub_sub_lib",
stem: "output_file_name", // .so will be added automatically to out file name.
compile_multilib: "both",
multilib: {
lib32: {
srcs: ["path for src 32bit lib"],
},
lib64: {
srcs: ["path for src 64bit lib"],
},
},
strip: {
none:true,
},
allow_undefined_symbols: true,
check_elf_files: false,
vendor: true,
enabled: true,
}
product_mk file :
...
PRODUCT_PACKAGES += product_package_name_in_MK_file
...
I'm trying to build the wireguard-android sources on my windows machine, fixing the problems step by step with trial and error.
I have CMake and Make installed, the first problem I encountered was the 'bad' value reported by uname (mingw64), not matching with the golang filenames hosted by Google.
I've edited (hacked) the make file to point to the real filename of the windows version (amd64). The problem is the windows version has a .zip extension instead of .tar.gzand the result from zip doesn't seem compatible with the piped command.
Original command:
curl "https://dl.google.com/go/go$(DESIRED_GO_VERSION).$(shell uname -s | tr '[:upper:]' '[:lower:]')-$(NDK_GO_ARCH_MAP_$(shell uname -m)).tar.gz" | tar -C "$(dir $#)" --strip-components=1 -xzf -
My attempted changes:
(uses an if-else because it still needs to run on mac too)
ifeq "msys" "$(shell uname -o | tr '[:upper:]' '[:lower:]')"
# Note: when enclosed in the ifeq, the ARCH_MAP part no longer worked
# Note: using tar with the zip fails, because we cant untar a zip (signal 13)
# Note: using unzip with the zip fails with confusing paths
curl "https://dl.google.com/go/go$(DESIRED_GO_VERSION).windows-amd64.zip" | unzip -C "$(dir $#)" --strip-components=1 -xzf -
else
curl "https://dl.google.com/go/go$(DESIRED_GO_VERSION).$(shell uname -s | tr '[:upper:]' '[:lower:]')-$(NDK_GO_ARCH_MAP_$(shell uname -m)).tar.gz" | tar -C "$(dir $#)" --strip-components=1 -xzf -
endif
Resulting error if using unzip:
unzip: cannot find or open C:\wireguard-android\app\build\intermediates\cmake\debug\obj\armeabi-v7a/../generated-src/go-1.13.7/, C:\wireguard-android\app\build\intermediates\cmake\debug\obj\armeabi-v7a/../generated-src/go-1.13.7/.zip or C:\wireguard-android\app\build\intermediates\cmake\debug\obj\armeabi-v7a/../generated-src/go-1.13.7/.ZIP.
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
0 127M 0 5419 0 0 26694 0 1:23:47 --:--:-- 1:23:47 26694
curl: (23) Failed writing body (34 != 1357)
make: *** [C:\wireguard-android\app\build\intermediates\cmake\debug\obj\armeabi-v7a/../generated-src/go-1.13.7/.prepared] Error 9
Resulting error if using tar:
curl "https://dl.google.com/go/go1.13.7.windows-amd64.zip" | tar -C "C:\wireguard-android\app\build\intermediates\cmake\debug\obj\armeabi-v7a/../generated-src/go-1.13.7/" --strip-components=1 -xzf -
% Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0gzip: stdin has more than one entry--rest ignored
tar: Child died with signal 13
tar: Error is not recoverable: exiting now
0 127M 0 108k 0 0 248k 0 0:08:47 --:--:-- 0:08:47 248k
curl: (23) Failed writing body (738 != 1357)
make: *** [C:\wireguard-android\app\build\intermediates\cmake\debug\obj\armeabi-v7a/../generated-src/go-1.13.7/.prepared] Error 2
How should I get this command working? (With either tar or zip/unzip)
Somebody pointed out to me, that maybe I need the Android distro, not the Windows one. In that case I would assume I need armeabi-v7a, but I can only see ARMv6 and ARMv8 packages. What distribution should I use?
I've managed to solve this, I'm answering my own question rather than deleting because I think this will eventually help another developer.
First some clarifications:
It may seem like you should be including the target-platform Go libs (i.e. ARM for Android), but if you try this, you will get an error that the file is not executable when building. (So the build platform is the version to match, i.e. Windows here)
Because Google provides the Windows libs as a Zip (vs tar.gz for other platforms), you cannot use the tar command.
Because zip's cannot be read from a curl stream (the index is at the end of the file), you need to download the file and then unzip. Some people have suggested to use the jar command, however this did not work successfully with cmake/make
The zip file will be extracted into a subdirectory 'go' inside of whichever path you choose. For this reason you need to modify the paths
Some of the commands on Windows would not accept .. as the middle of a path, so I had to modify the CMakeLists file to use an absolute path
The changed end of the Makefile: (from after the .prepared/mkdir statements)
# Warning the (lack-of) indentation here is critical https://stackoverflow.com/a/4483467/984830
# Note: I've hardcoded the windows filename below, so you'll need to do an `if` (like in my question) if you want to support other platforms as well
curl -o "$(BUILDDIR)/go-$(DESIRED_GO_VERSION)/gofile.zip" "https://dl.google.com/go/go$(DESIRED_GO_VERSION).windows-amd64.zip"
unzip -o "$(BUILDDIR)/go-$(DESIRED_GO_VERSION)/gofile.zip" -d "$(dir $#)"
rm -f "$(BUILDDIR)/go-$(DESIRED_GO_VERSION)/gofile.zip"
patch -p1 -f -N -r- -d "$(dir $#)go/" < goruntime-boottime-over-monotonic.diff
touch "$#"
$(DESTDIR)/libwg-go.so: export PATH := $(BUILDDIR)/go-$(DESIRED_GO_VERSION)/go/bin/:$(PATH)
$(DESTDIR)/libwg-go.so: $(BUILDDIR)/go-$(DESIRED_GO_VERSION)/.prepared go.mod
go build -tags linux -ldflags="-X golang.zx2c4.com/wireguard/ipc.socketDirectory=/data/data/$(ANDROID_PACKAGE_NAME)/cache/wireguard" -v -trimpath -o "$#" -buildmode c-shared
The changed end of the CMakeLists file: (replacing the add_custom_target section)
# added a new variable to get the parent dir without using .. in the path
get_filename_component(destdirparent "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/.." ABSOLUTE)
# referred to the variable on the last line of this statment
add_custom_target(libwg-go.so WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/libwg-go" COMMENT "Building wireguard-go" VERBATIM COMMAND make
ANDROID_ARCH_NAME=${ANDROID_ARCH_NAME}
ANDROID_C_COMPILER=${ANDROID_C_COMPILER}
ANDROID_TOOLCHAIN_ROOT=${ANDROID_TOOLCHAIN_ROOT}
ANDROID_LLVM_TRIPLE=${ANDROID_LLVM_TRIPLE}
ANDROID_SYSROOT=${ANDROID_SYSROOT}
ANDROID_PACKAGE_NAME=${ANDROID_PACKAGE_NAME}
CFLAGS=${CMAKE_C_FLAGS}\ -Wno-unused-command-line-argument
LDFLAGS=${CMAKE_SHARED_LINKER_FLAGS}\ -fuse-ld=gold
DESTDIR=${CMAKE_LIBRARY_OUTPUT_DIRECTORY}
BUILDDIR=${destdirparent}/generated-src
)
For reference the original files are here: Makefile & CMakeLists and are mirrored on Github
Thanks for #Nick Cardoso's answer. After repeated modification and debugging, I successfully worked out the makefile and CMakeLists.txt available on the Windows platform.
When using, you only need to modify these three variables: GIT_BIN_PATH, DESIRED_GO_VERSION, MAKE_PATH.
Notes:
No spaces are allowed in the project path! Otherwise the path of CURDIR will be truncated
Don't install Cygwin! All you need is Git and the NDK, because Git contains the required commands: unzip.exe, patch.exe and touch.exe
tunnel/tools/libwg-go/Makefile
# SPDX-License-Identifier: Apache-2.0
#
# Copyright © 2017-2019 WireGuard LLC. All Rights Reserved.
BUILDDIR ?= $(CURDIR)/build
DESTDIR ?= $(CURDIR)/out
NDK_GO_ARCH_MAP_x86 := 386
NDK_GO_ARCH_MAP_x86_64 := amd64
NDK_GO_ARCH_MAP_arm := arm
NDK_GO_ARCH_MAP_arm64 := arm64
NDK_GO_ARCH_MAP_mips := mipsx
NDK_GO_ARCH_MAP_mips64 := mips64x
CLANG_FLAGS := --target=$(ANDROID_LLVM_TRIPLE) --gcc-toolchain=$(ANDROID_TOOLCHAIN_ROOT) --sysroot=$(ANDROID_SYSROOT)
export CGO_CFLAGS := $(CLANG_FLAGS) $(CFLAGS)
export CGO_LDFLAGS := $(CLANG_FLAGS) $(LDFLAGS) -Wl,-soname=libwg-go.so
export CC := $(ANDROID_C_COMPILER)
export GOARCH := $(NDK_GO_ARCH_MAP_$(ANDROID_ARCH_NAME))
export GOOS := android
export CGO_ENABLED := 1
default: $(DESTDIR)/libwg-go.so
GIT_BIN_PATH := "D:\Program Files\Git\usr\bin"
UNZIP_PATH := $(GIT_BIN_PATH)\unzip.exe
PATCH_PATH := $(GIT_BIN_PATH)\patch.exe
TOUCH_PATH := $(GIT_BIN_PATH)\touch.exe
DESIRED_GO_VERSION := 1.16.3
$(BUILDDIR)/go-$(DESIRED_GO_VERSION)/.prepared:
if not exist "$(dir $#)" mkdir "$(dir $#)"
curl -o "$(BUILDDIR)\go-$(DESIRED_GO_VERSION)\gofile.zip" "https://dl.google.com/go/go$(DESIRED_GO_VERSION).windows-amd64.zip"
$(UNZIP_PATH) -o "$(BUILDDIR)\go-$(DESIRED_GO_VERSION)\gofile.zip" -d "$(dir $#)"
del /f "$(BUILDDIR)\go-$(DESIRED_GO_VERSION)\gofile.zip"
$(PATCH_PATH) -p1 -f -N -r- -d "$(dir $#)go/" < goruntime-boottime-over-monotonic.diff
$(TOUCH_PATH) "$#"
$(DESTDIR)/libwg-go.so: export PATH := $(BUILDDIR)/go-$(DESIRED_GO_VERSION)/go/bin/:$(PATH)
$(DESTDIR)/libwg-go.so: $(BUILDDIR)/go-$(DESIRED_GO_VERSION)/.prepared go.mod
go build -tags linux -ldflags="-X golang.zx2c4.com/wireguard/ipc.socketDirectory=/data/data/$(ANDROID_PACKAGE_NAME)/cache/wireguard" -v -trimpath -o "$#" -buildmode c-shared
.DELETE_ON_ERROR:
/tunnel/tools/CMakeLists.txt
# SPDX-License-Identifier: Apache-2.0
#
# Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
cmake_minimum_required(VERSION 3.4.1)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}")
# Work around https://github.com/android-ndk/ndk/issues/602
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=gold")
file(GLOB WG_SOURCES wireguard-tools/src/*.c ndk-compat/compat.c)
add_executable(libwg.so ${WG_SOURCES})
target_include_directories(libwg.so PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/wireguard-tools/src/uapi/linux/" "${CMAKE_CURRENT_SOURCE_DIR}/wireguard-tools/src/")
target_compile_options(libwg.so PUBLIC -O3 -std=gnu11 -D_GNU_SOURCE -include ${CMAKE_CURRENT_SOURCE_DIR}/ndk-compat/compat.h -DHAVE_VISIBILITY_HIDDEN -DRUNSTATEDIR=\"/data/data/${ANDROID_PACKAGE_NAME}/cache\")
get_filename_component(destdirparent "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/.." ABSOLUTE)
set(MAKE_PATH "D:/AndroidSDK/ndk/21.1.6352462/prebuilt/windows-x86_64/bin/make.exe")
# referred to the variable on the last line of this statment
add_custom_target(libwg-go.so WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/libwg-go" COMMENT "Building wireguard-go" VERBATIM COMMAND ${MAKE_PATH}
ANDROID_ARCH_NAME=${ANDROID_ARCH_NAME}
ANDROID_C_COMPILER=${ANDROID_C_COMPILER}
ANDROID_TOOLCHAIN_ROOT=${ANDROID_TOOLCHAIN_ROOT}
ANDROID_LLVM_TRIPLE=${ANDROID_LLVM_TRIPLE}
ANDROID_SYSROOT=${ANDROID_SYSROOT}
ANDROID_PACKAGE_NAME=${ANDROID_PACKAGE_NAME}
CFLAGS=${CMAKE_C_FLAGS}\ -Wno-unused-command-line-argument
LDFLAGS=${CMAKE_SHARED_LINKER_FLAGS}\ -fuse-ld=gold
DESTDIR=${CMAKE_LIBRARY_OUTPUT_DIRECTORY}
BUILDDIR=${destdirparent}/generated-src
)
# Hack to make it actually build as part of the default target
add_dependencies(libwg.so libwg-go.so)
I keep getting an error when trying to create an apk with python-for-android. When I run this:
p4a apk --debug --sdk_dir=sdk --ndk_dir=ndk --ndk_version=r16b --private mnt/c/main.py --package=helloworld --name "Hello World" --version 0.1 --bootstrap=sdl2 --requirements=python2,kivy --arch=armeabi-v7a
I get the following error:
[INFO]: Will compile for the following archs: armeabi-v7a
[INFO]: Found Android API target in $ANDROIDAPI
[ERROR]: Could not find `android` or `sdkmanager` binaries in Android SDK. Exiting.
Traceback (most recent call last):
File "/usr/local/bin/p4a", line 11, in <module>
sys.exit(main())
File "/usr/local/lib/python2.7/dist-packages/pythonforandroid/toolchain.py", line 975, in main
ToolchainCL()
File "/usr/local/lib/python2.7/dist-packages/pythonforandroid/toolchain.py", line 512, in __init__
getattr(self, args.subparser_name.replace('-', '_'))(args)
File "/usr/local/lib/python2.7/dist-packages/pythonforandroid/toolchain.py", line 144, in wrapper_func
user_ndk_ver=self.ndk_version)
File "/usr/local/lib/python2.7/dist-packages/pythonforandroid/build.py", line 238, in prepare_build_environment
apis = [s for s in targets if re.match(r'^ *API level: ', s)]
UnboundLocalError: local variable 'targets' referenced before assignment
I am using Ubuntu 16.04. Here is my .bashrc file (scroll to bottom to see my additions):
# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
# don't put duplicate lines or lines starting with space in the history.
# See bash(1) for more options
HISTCONTROL=ignoreboth
# append to the history file, don't overwrite it
shopt -s histappend
# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
HISTSIZE=1000
HISTFILESIZE=2000
# check the window size after each command and, if necessary,
# update the values of LINES and COLUMNS.
shopt -s checkwinsize
# If set, the pattern "**" used in a pathname expansion context will
# match all files and zero or more directories and subdirectories.
#shopt -s globstar
# make less more friendly for non-text input files, see lesspipe(1)
[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"
# set variable identifying the chroot you work in (used in the prompt below)
if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then
debian_chroot=$(cat /etc/debian_chroot)
fi
# set a fancy prompt (non-color, unless we know we "want" color)
case "$TERM" in
xterm-color) color_prompt=yes;;
esac
# uncomment for a colored prompt, if the terminal has the capability; turned
# off by default to not distract the user: the focus in a terminal window
# should be on the output of commands, not on the prompt
#force_color_prompt=yes
if [ -n "$force_color_prompt" ]; then
if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
# We have color support; assume it's compliant with Ecma-48
# (ISO/IEC-6429). (Lack of such support is extremely rare, and such
# a case would tend to support setf rather than setaf.)
color_prompt=yes
else
color_prompt=
fi
fi
if [ "$color_prompt" = yes ]; then
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u#\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
else
PS1='${debian_chroot:+($debian_chroot)}\u#\h:\w\$ '
fi
unset color_prompt force_color_prompt
# If this is an xterm set the title to user#host:dir
case "$TERM" in
xterm*|rxvt*)
PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u#\h: \w\a\]$PS1"
;;
*)
;;
esac
# enable color support of ls and also add handy aliases
if [ -x /usr/bin/dircolors ]; then
test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
alias ls='ls --color=auto'
#alias dir='dir --color=auto'
#alias vdir='vdir --color=auto'
alias grep='grep --color=auto'
alias fgrep='fgrep --color=auto'
alias egrep='egrep --color=auto'
fi
# some more ls aliases
alias ll='ls -alF'
alias la='ls -A'
alias l='ls -CF'
# Add an "alert" alias for long running commands. Use like so:
# sleep 10; alert
alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''
s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'
# Alias definitions.
# You may want to put all your additions into a separate file like
# ~/.bash_aliases, instead of adding them here directly.
# See /usr/share/doc/bash-doc/examples in the bash-doc package.
if [ -f ~/.bash_aliases ]; then
. ~/.bash_aliases
fi
# enable programmable completion features (you don't need to enable
# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
# sources /etc/bash.bashrc).
if ! shopt -oq posix; then
if [ -f /usr/share/bash-completion/bash_completion ]; then
. /usr/share/bash-completion/bash_completion
elif [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi
fi
export ANDROIDSDK="~/sdk"
export ANDROIDNDK="~/ndk"
export ANDROIDAPI="19"
export ANDROIDNDKVER="r16b"
Note I downloaded the ndk from (https://developer.android.com/ndk/downloads/index.html) and the sdk from (https://developer.android.com/studio/index.html). I also installed platform tools and build-tools with sdkmanager. I am a complete beginner to python-for-android, so any help is greatly appreciated.
Error is pretty straightforward, you have a problem with SDK:
[ERROR]: Could not find android or sdkmanager binaries in
Android SDK. Exiting.
I'm not sure about how to make things right with Studio, but link to SDK that works:
https://dl.google.com/android/android-sdk_r24.4.1-linux.tgz
I am curling the latest Android Studio dmg file, mounting the image and copying the .app directory into the Applications directory. When I attempt to open the directory I receive this warning, and when I query the application state, I also receive the code below. Any idea how I can generically install Android Studio from the cli?
Warning:
"Android Studio" is damaged and can't be opened. You should move it to the Trash. Google Chrome.app downloaded this file on
...
| => spctl -a /Applications/Android\ Studio.app/
/Applications/Android Studio.app/: a sealed resource is missing or invalid
...
| => codesign --display --verbose=4 /Applications/Android\ Studio.app/
Executable=/Applications/Android Studio.app/Contents/MacOS/studio
Identifier=com.google.android.studio
Format=app bundle with Mach-O universal (i386 x86_64)
CodeDirectory v=20200 size=537 flags=0x0(none) hashes=11+3 location=embedded
OSPlatform=36
OSSDKVersion=657664
OSVersionMin=657408
Hash type=sha256 size=32
CandidateCDHash sha1=4456b3e77035b4318af16276667c88f7b7d4f9ac
CandidateCDHash sha256=6d95335c6815111d93abd1e87b9fd4648d991bdd
Hash choices=sha1,sha256
Page size=4096
CDHash=6d95335c6815111d93abd1e87b9fd4648d991bdd
Signature size=8948
Authority=Developer ID Application: Google, Inc. (EQHXZ8M8AV)
Authority=Developer ID Certification Authority
Authority=Apple Root CA
Timestamp=Dec 1, 2016, 4:57:25 PM
Info.plist entries=22
TeamIdentifier=EQHXZ8M8AV
Sealed Resources version=2 rules=12 files=11250
Internal requirements count=1 size=188
Android Install Script
#!/usr/bin/env bash
echo "Installing Android Studio"
ANDROID_STUDIO_DMG=$(curl -0 https://developer.android.com/studio/index.html | grep -o --regexp='https://dl.google.com/dl/android/studio/install/[a-zA-Z0-9./?=_-]*/android-studio-ide-[a-zA-Z0-9./?=_-]*-mac.dmg')
./dmginstall.sh $ANDROID_STUDIO_DMG
DMG Install Script - (Modified:https://gist.github.com/rahulgautam/6695872)
#!/usr/bin/env bash
# Downloads and install a .dmg from a URL
#
# Usage
# $ dmginstall [url]
#
# For example, for installing android-studio-ide
# $ dmginstall https://dl.google.com/dl/android/studio/install/2.2.3.0/android-studio-ide-145.3537739-mac.dmg
#
# TODO
# - currently only handles .dmg with .app folders, not .pkg files
# - handle .zip files as well
if [[ $# -lt 1 ]]; then
echo "Usage: dmginstall [url]"
exit 1
fi
url=$*
# Generate a random file name
tmp_file=/tmp/`openssl rand -base64 10 | tr -dc '[:alnum:]'`.dmg
# Download file
echo "Downloading $url..."
curl -# -L -o $tmp_file $url
echo "Please copy and paste the Volumes directory you would like to use"
echo "-----------------------------------------------------------------"
hdiutil mount $tmp_file
IFS= read -r -p "Enter volume: " volume
echo "$volume"
# Locate .app folder and move to /Applications
app=`find "$volume" -name *.app -maxdepth 1 -type d -print0`
echo "Copying `echo $app | awk -F/ '{print $NF}'` into /Applications..."
cp -rv "$app" '/Applications'
# Unmount volume, delete temporal file
echo "Cleaning up..."
hdiutil unmount "$volume"
rm "$tmp_file"
echo "Done!"
In my bash script I can build my Android Studio project like this:
#!/bin/bash
./gradlew assembleRelease
That creates .apk file in project's build folder but I don't know the path to that folder inside my script.Is there any way to get it?
You could add a line 'finding' it-
path=`find ./ -name "*.apk"`
echo "$path"
If you want the absolute path-
path=`find ./ \`pwd\` . -name "*.apk"`
echo "$path"
Since there's counting views for the question I post the final version of the solution suggested by #Chem-man17
# ---------------- Copy .apk file to output folder -----------------------
mkdir -p "$OUTPUT_DIR"
APK_FILE=`find ${PWD}/app/build/apk -type f -name "*.apk" -printf '%T# %p\n' \
| sort -k 1nr \
| head -n1 \
| sed 's/^[^ ]* //'`
APK_NAME=`echo $APK_FILE | xargs -I{} basename {}`
mv $APK_FILE $OUTPUT_DIR
echo "--- Created file: $OUTPUT_DIR/$APK_NAME"
Basically it sorts .apks in build folder by date and grabs the most recent