diff --git a/android/.gitignore b/android/.gitignore new file mode 100644 index 000000000..94b83ee4a --- /dev/null +++ b/android/.gitignore @@ -0,0 +1,16 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +app/src/main/jnilibs/ diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml deleted file mode 100644 index 447a68251..000000000 --- a/android/AndroidManifest.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/android/apk/make-unsigned-apk.sh b/android/apk/make-unsigned-apk.sh deleted file mode 100755 index 3bc4009fe..000000000 --- a/android/apk/make-unsigned-apk.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh -e - -S=`dirname "$0"` -ANDROID_ABI=$1 -STRIP=$2 -ZIP=$3 -UNSIGNED_APK=$4 -LIBMPD_SO=$5 -CLASSES_DEX=$6 -RESOURCES_APK=$7 -D=`dirname "$UNSIGNED_APK"` - -rm -rf "$D/apk" -mkdir -p "$D/apk/lib/$ANDROID_ABI" - -"$STRIP" "$LIBMPD_SO" -o "$D/apk/lib/$ANDROID_ABI/`basename $LIBMPD_SO`" -cp "$CLASSES_DEX" "$D/apk/" -cp "$RESOURCES_APK" "$UNSIGNED_APK" - -cd "$D/apk" -exec zip -q -r -X "../`basename $UNSIGNED_APK`" . diff --git a/android/apk/meson.build b/android/apk/meson.build index 0ee395852..72fefa102 100644 --- a/android/apk/meson.build +++ b/android/apk/meson.build @@ -1,58 +1,13 @@ -unsigned_apk = custom_target( - 'mpd-unsigned.apk', - output: 'mpd-unsigned.apk', - input: [mpd, classes_dex, resources_apk[0]], +android_abi = get_option('android_abi') + +mpd_so = custom_target( + 'libmpd.so', + output: 'libmpd.so', + input: mpd, command: [ - join_paths(meson.current_source_dir(), 'make-unsigned-apk.sh'), - android_abi, - get_option('android_strip'), - zip, - '@OUTPUT0@', + 'cp', '@INPUT@', + join_paths(meson.current_source_dir(), '../app/src/main/jnilibs/', android_abi), ], + build_by_default: true ) - -aligned_apk = custom_target( - 'mpd-aligned.apk', - output: 'mpd-aligned.apk', - input: unsigned_apk, - command: [ - android_zipalign, - '-f', '4', - '@INPUT@', '@OUTPUT@', - ], -) - -if get_option('android_debug_keystore') != '' - debug_apk = custom_target( - 'mpd-debug.apk', - output: 'mpd-debug.apk', - input: aligned_apk, - command: [ - android_apksigner, 'sign', - '--in', '@INPUT@', - '--out', '@OUTPUT@', - '--debuggable-apk-permitted', - '-ks', get_option('android_debug_keystore'), - '--ks-key-alias', 'androiddebugkey', - '--ks-pass', 'pass:android', - ], - build_by_default: true - ) -endif - -if get_option('android_keystore') != '' and get_option('android_keyalias') != '' and get_option('android_keypass') != '' - unaligned_apk = custom_target( - 'mpd.apk', - output: 'mpd.apk', - input: aligned_apk, - command: [ - android_apksigner, 'sign', - '--in', '@INPUT@', - '--out', '@OUTPUT@', - '-ks', get_option('android_keystore'), - '--ks-key-alias', get_option('android_keyalias'), - '--ks-pass', 'pass:' + get_option('android_keypass'), - ], - ) -endif diff --git a/android/app/.gitignore b/android/app/.gitignore new file mode 100644 index 000000000..42afabfd2 --- /dev/null +++ b/android/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts new file mode 100644 index 000000000..f6fdbf5a8 --- /dev/null +++ b/android/app/build.gradle.kts @@ -0,0 +1,38 @@ +plugins { + id("com.android.application") +} + +android { + namespace = "org.musicpd" + compileSdk = 34 + + defaultConfig { + applicationId = "org.musicpd" + minSdk = 24 + targetSdk = 30 + versionCode = 1 + versionName = "1.0" + } + + buildFeatures { + aidl = true + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } +} + +dependencies { + implementation("androidx.appcompat:appcompat:1.6.1") +} \ No newline at end of file diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml new file mode 100644 index 000000000..d35d06883 --- /dev/null +++ b/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/src/IMain.aidl b/android/app/src/main/aidl/org/musicpd/IMain.aidl similarity index 100% rename from android/src/IMain.aidl rename to android/app/src/main/aidl/org/musicpd/IMain.aidl diff --git a/android/src/IMainCallback.aidl b/android/app/src/main/aidl/org/musicpd/IMainCallback.aidl similarity index 100% rename from android/src/IMainCallback.aidl rename to android/app/src/main/aidl/org/musicpd/IMainCallback.aidl diff --git a/android/app/src/main/ic_launcher-playstore.png b/android/app/src/main/ic_launcher-playstore.png new file mode 100644 index 000000000..9c27e1a7c Binary files /dev/null and b/android/app/src/main/ic_launcher-playstore.png differ diff --git a/android/src/Bridge.java b/android/app/src/main/java/org/musicpd/Bridge.java similarity index 100% rename from android/src/Bridge.java rename to android/app/src/main/java/org/musicpd/Bridge.java diff --git a/android/src/Loader.java b/android/app/src/main/java/org/musicpd/Loader.java similarity index 100% rename from android/src/Loader.java rename to android/app/src/main/java/org/musicpd/Loader.java diff --git a/android/src/Main.java b/android/app/src/main/java/org/musicpd/Main.java similarity index 97% rename from android/src/Main.java rename to android/app/src/main/java/org/musicpd/Main.java index 0076e55aa..e943a6089 100644 --- a/android/src/Main.java +++ b/android/app/src/main/java/org/musicpd/Main.java @@ -23,11 +23,14 @@ import android.os.RemoteException; import android.util.Log; import android.widget.RemoteViews; +import androidx.core.app.ServiceCompat; + import java.lang.reflect.Constructor; import java.lang.reflect.Method; public class Main extends Service implements Runnable { private static final String TAG = "Main"; + private static final String WAKELOCK_TAG = "mpd:wakelockmain"; private static final String REMOTE_ERROR = "MPD process was killed"; private static final int MAIN_STATUS_ERROR = -1; private static final int MAIN_STATUS_STOPPED = 0; @@ -198,7 +201,7 @@ public class Main extends Service implements Runnable { mainIntent.setAction("android.intent.action.MAIN"); mainIntent.addCategory("android.intent.category.LAUNCHER"); final PendingIntent contentIntent = PendingIntent.getActivity(this, 0, - mainIntent, PendingIntent.FLAG_CANCEL_CURRENT); + mainIntent, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE); Notification.Builder nBuilder; if (Build.VERSION.SDK_INT >= 26 /* Build.VERSION_CODES.O */) @@ -262,7 +265,7 @@ public class Main extends Service implements Runnable { private void setWakelockEnabled(boolean enabled) { if (enabled && mWakelock == null) { PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE); - mWakelock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); + mWakelock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_TAG); mWakelock.acquire(); Log.d(TAG, "Wakelock acquired"); } else if (!enabled && mWakelock != null) { diff --git a/android/src/Receiver.java b/android/app/src/main/java/org/musicpd/Receiver.java similarity index 100% rename from android/src/Receiver.java rename to android/app/src/main/java/org/musicpd/Receiver.java diff --git a/android/src/Settings.java b/android/app/src/main/java/org/musicpd/Settings.java similarity index 100% rename from android/src/Settings.java rename to android/app/src/main/java/org/musicpd/Settings.java diff --git a/android/app/src/main/res/drawable/ic_banner_foreground.xml b/android/app/src/main/res/drawable/ic_banner_foreground.xml new file mode 100644 index 000000000..42bded022 --- /dev/null +++ b/android/app/src/main/res/drawable/ic_banner_foreground.xml @@ -0,0 +1,239 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/res/drawable/ic_launcher_foreground.xml b/android/app/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 000000000..d62cbb5ea --- /dev/null +++ b/android/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,235 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/res/drawable/notification_icon.png b/android/app/src/main/res/drawable/notification_icon.png new file mode 100644 index 000000000..e77d87aa8 Binary files /dev/null and b/android/app/src/main/res/drawable/notification_icon.png differ diff --git a/android/res/layout/custom_notification_gb.xml b/android/app/src/main/res/layout/custom_notification_gb.xml similarity index 100% rename from android/res/layout/custom_notification_gb.xml rename to android/app/src/main/res/layout/custom_notification_gb.xml diff --git a/android/res/layout/log_item.xml b/android/app/src/main/res/layout/log_item.xml similarity index 100% rename from android/res/layout/log_item.xml rename to android/app/src/main/res/layout/log_item.xml diff --git a/android/res/layout/settings.xml b/android/app/src/main/res/layout/settings.xml similarity index 100% rename from android/res/layout/settings.xml rename to android/app/src/main/res/layout/settings.xml diff --git a/android/app/src/main/res/mipmap-anydpi-v26/ic_banner.xml b/android/app/src/main/res/mipmap-anydpi-v26/ic_banner.xml new file mode 100644 index 000000000..a0a0dece9 --- /dev/null +++ b/android/app/src/main/res/mipmap-anydpi-v26/ic_banner.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 000000000..7353dbd1f --- /dev/null +++ b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 000000000..7353dbd1f --- /dev/null +++ b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/mipmap-hdpi/ic_banner.png b/android/app/src/main/res/mipmap-hdpi/ic_banner.png new file mode 100644 index 000000000..6932f1f52 Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_banner.png differ diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/android/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 000000000..a6f593b3b Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.webp differ diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 000000000..d4214700e Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_banner.png b/android/app/src/main/res/mipmap-mdpi/ic_banner.png new file mode 100644 index 000000000..23982b0ff Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_banner.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/android/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 000000000..b23f35386 Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.webp differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 000000000..4e3388e10 Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_banner.png b/android/app/src/main/res/mipmap-xhdpi/ic_banner.png new file mode 100644 index 000000000..3d0c2fc49 Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_banner.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 000000000..7c4cbb4d5 Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 000000000..a40719ac8 Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_banner.png b/android/app/src/main/res/mipmap-xxhdpi/ic_banner.png new file mode 100644 index 000000000..03fc51895 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_banner.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 000000000..be1eb31b0 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 000000000..2fd0829f3 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_banner.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_banner.png new file mode 100644 index 000000000..30887f8c8 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_banner.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 000000000..0297013ca Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 000000000..72ea5bcab Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ diff --git a/android/app/src/main/res/values/ic_banner_background.xml b/android/app/src/main/res/values/ic_banner_background.xml new file mode 100644 index 000000000..15db34b81 --- /dev/null +++ b/android/app/src/main/res/values/ic_banner_background.xml @@ -0,0 +1,4 @@ + + + #FFFFFF + \ No newline at end of file diff --git a/android/app/src/main/res/values/ic_launcher_background.xml b/android/app/src/main/res/values/ic_launcher_background.xml new file mode 100644 index 000000000..c5d5899fd --- /dev/null +++ b/android/app/src/main/res/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #FFFFFF + \ No newline at end of file diff --git a/android/res/values/strings.xml b/android/app/src/main/res/values/strings.xml similarity index 100% rename from android/res/values/strings.xml rename to android/app/src/main/res/values/strings.xml diff --git a/android/build.gradle.kts b/android/build.gradle.kts new file mode 100644 index 000000000..c21801c71 --- /dev/null +++ b/android/build.gradle.kts @@ -0,0 +1,4 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +plugins { + id("com.android.application") version "8.1.2" apply false +} \ No newline at end of file diff --git a/android/gradle.properties b/android/gradle.properties new file mode 100644 index 000000000..a03b35489 --- /dev/null +++ b/android/gradle.properties @@ -0,0 +1,21 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app's APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Enables namespacing of each library's R class so that its R class includes only the +# resources declared in the library itself and none from the library's dependencies, +# thereby reducing the size of the R class for that library +android.nonTransitiveRClass=true diff --git a/android/gradle/wrapper/gradle-wrapper.jar b/android/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 000000000..e708b1c02 Binary files /dev/null and b/android/gradle/wrapper/gradle-wrapper.jar differ diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..0c338ad87 --- /dev/null +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Sun Dec 17 15:00:03 CST 2023 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/android/gradlew b/android/gradlew new file mode 100755 index 000000000..4f906e0c8 --- /dev/null +++ b/android/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# 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 +# +# https://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. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/android/gradlew.bat b/android/gradlew.bat new file mode 100644 index 000000000..ac1b06f93 --- /dev/null +++ b/android/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/android/make-resources-apk.sh b/android/make-resources-apk.sh deleted file mode 100755 index bee1f4c81..000000000 --- a/android/make-resources-apk.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh -e - -S=`dirname "$0"` -AAPT=$1 -BASE_JAR=$2 -JAVA_PKG=$3 -JAVA_PKG_PATH=$4 -APK_FILE="$5" -D=`dirname "$APK_FILE"` - -rm -rf "$D/res" -mkdir -p "$D/res/drawable" "$D/src" -cp "$D/icon.png" "$D/notification_icon.png" "$D/res/drawable/" - -"$AAPT" package -f -m --auto-add-overlay \ - --custom-package "$JAVA_PKG" \ - -M "$S/AndroidManifest.xml" \ - -S "$D/res" \ - -S "$S/res" \ - -J "$D/src" \ - -I "$BASE_JAR" \ - -F "$D/resources.apk" - -cp "$D/src/$JAVA_PKG_PATH/R.java" "$D/" diff --git a/android/meson.build b/android/meson.build index 66adb38b0..9e584058a 100644 --- a/android/meson.build +++ b/android/meson.build @@ -11,130 +11,24 @@ android_sdk_platform = 'android-29' android_build_tools_dir = join_paths(android_sdk, 'build-tools', android_sdk_build_tools_version) android_sdk_platform_dir = join_paths(android_sdk, 'platforms', android_sdk_platform) -android_aidl = join_paths(android_build_tools_dir, 'aidl') -android_aapt = join_paths(android_build_tools_dir, 'aapt') -android_dx = join_paths(android_build_tools_dir, 'dx') -android_zipalign = join_paths(android_build_tools_dir, 'zipalign') -android_apksigner = join_paths(android_build_tools_dir, 'apksigner') + +android_gradlew = join_paths(meson.current_source_dir(), 'gradlew') javac = find_program('javac') -rsvg_convert = find_program('rsvg-convert') -convert = find_program('convert') -zip = find_program('zip') common_cppflags += '-I' + join_paths(meson.current_build_dir(), 'include') -# -# AIDL -# - -IMainCallback_java = custom_target( - 'IMainCallback.java', - output: 'IMainCallback.java', - input: join_paths(meson.current_source_dir(), 'src', 'IMainCallback.aidl'), - command: [ - join_paths(meson.current_source_dir(), 'run-aidl.sh'), - android_aidl, - '@INPUT@', - '@OUTPUT@', - join_paths(meson.current_build_dir(), 'src'), - android_package_path, - ], -) - -IMain_java = custom_target( - 'IMain.java', - output: 'IMain.java', - input: join_paths(meson.current_source_dir(), 'src', 'IMain.aidl'), - depends: IMainCallback_java, - command: [ - join_paths(meson.current_source_dir(), 'run-aidl.sh'), - android_aidl, - '@INPUT@', - '@OUTPUT@', - join_paths(meson.current_build_dir(), 'src'), - android_package_path, - ], -) - -# -# Resources -# - -android_icon = custom_target( - 'Android icon', - output: 'icon.png', - input: '../mpd.svg', - command: [ - rsvg_convert, '--width=48', '--height=48', '@INPUT@', '-o', '@OUTPUT@', - ], -) - -android_notification_icon = custom_target( - 'Android notification icon', - output: 'notification_icon.png', - input: android_icon, - command: [ - convert, '@INPUT@', '-colorspace', 'Gray', '-gamma', '2.2', '@OUTPUT@', - ], -) - -resources_apk = custom_target( - 'resources.apk', - output: ['resources.apk', 'R.java'], +bridge_header = custom_target( + 'org_musicpd_Bridge.h', + output: 'org_musicpd_Bridge.h', input: [ - 'res/layout/custom_notification_gb.xml', - 'res/layout/log_item.xml', - 'res/layout/settings.xml', - 'res/values/strings.xml', - android_icon, - android_notification_icon, - ], - command: [ - join_paths(meson.current_source_dir(), 'make-resources-apk.sh'), - android_aapt, - join_paths(android_sdk_platform_dir, 'android.jar'), - android_package, - android_package_path, - '@OUTPUT0@', - ], -) - -# -# Compile Java -# - -classes_jar = custom_target( - 'classes.jar', - output: 'classes.jar', - input: [ - 'src/Bridge.java', - 'src/Loader.java', - 'src/Main.java', - 'src/Receiver.java', - 'src/Settings.java', - IMain_java, - IMainCallback_java, - resources_apk[1], + 'app/src/main/java/org/musicpd/Bridge.java', ], command: [ join_paths(meson.current_source_dir(), 'run-javac.sh'), javac, join_paths(android_sdk_platform_dir, 'android.jar'), - android_package_path, - zip, '@OUTPUT@', '@INPUT@', ], ) - -classes_dex = custom_target( - 'classes.dex', - output: 'classes.dex', - input: classes_jar, - command: [ - android_dx, - '--dex', '--output', '@OUTPUT@', - '@INPUT@', - ], -) diff --git a/android/run-aidl.sh b/android/run-aidl.sh deleted file mode 100755 index 986d75878..000000000 --- a/android/run-aidl.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh -e - -AIDL=$1 -SRC=$2 -DST=$3 -GENSRC=$4 -JAVA_PKG_PATH=$5 - -mkdir -p "$GENSRC/$JAVA_PKG_PATH" -cp "$SRC" "$GENSRC/$JAVA_PKG_PATH/" -"$AIDL" -I"$GENSRC" -o"$GENSRC" "$GENSRC/$JAVA_PKG_PATH/`basename $SRC`" -exec cp "$GENSRC/$JAVA_PKG_PATH/`basename $DST`" "$DST" diff --git a/android/run-javac.sh b/android/run-javac.sh index 843c29279..b279a72fa 100755 --- a/android/run-javac.sh +++ b/android/run-javac.sh @@ -2,24 +2,14 @@ JAVAC=$1 CLASSPATH=$2 -JAVA_PKG_PATH=$3 -ZIP=$4 -DIRNAME=`dirname "$5"` +DIRNAME=`dirname "$3"` REALDIR=`realpath "$DIRNAME"` -BASENAME=`basename "$5"` -JARFILE=$REALDIR/$BASENAME -shift 5 -D=`dirname "$JARFILE"` -GENSRC="$D/src" -GENCLASS="$D/classes" -GENINCLUDE="$D/include" +GENINCLUDE="$REALDIR/include" -mkdir -p "$GENSRC/$JAVA_PKG_PATH" +mkdir -p "$GENINCLUDE" "$JAVAC" -source 1.8 -target 1.8 -Xlint:-options \ -cp "$CLASSPATH" \ - -h "$GENINCLUDE" \ - -d "$GENCLASS" \ - "$@" -cd "$GENCLASS" -zip -q -r "$JARFILE" . + -h "$GENINCLUDE" \ + "$4" + diff --git a/android/settings.gradle.kts b/android/settings.gradle.kts new file mode 100644 index 000000000..c86ae3385 --- /dev/null +++ b/android/settings.gradle.kts @@ -0,0 +1,18 @@ +pluginManagement { + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + } +} + +rootProject.name = "MPD" +include(":app") + \ No newline at end of file diff --git a/doc/user.rst b/doc/user.rst index 273b57452..e2906c3d9 100644 --- a/doc/user.rst +++ b/doc/user.rst @@ -203,10 +203,8 @@ You need: * cmake * pkg-config * quilt -* imagemagick * zip * libtool -* rsvg-convert * python 3.9+ Just like with the native build, unpack the :program:`MPD` source @@ -221,7 +219,8 @@ tarball and change into the directory. Then, instead of --buildtype=debugoptimized -Db_ndebug=true \ -Dwrap_mode=forcefallback \ -Dandroid_debug_keystore=$HOME/.android/debug.keystore - ninja android/apk/mpd-debug.apk + cd ../../android + ./gradlew assembleDebug :envvar:`SDK_PATH` is the absolute path where you installed the Android SDK; :envvar:`NDK_PATH` is the Android NDK installation path; diff --git a/meson.build b/meson.build index 591ee3743..c1ad4d8a8 100644 --- a/meson.build +++ b/meson.build @@ -566,7 +566,7 @@ if is_android '-lz', ] more_deps += [ - declare_dependency(sources: [classes_jar]), + declare_dependency(sources: [bridge_header]), java_dep, ] else