├── .gitattributes ├── .gitignore ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── dev │ │ └── mishkun │ │ └── trycompose │ │ ├── MainActivity.kt │ │ └── SimpleComposable.kt │ └── res │ ├── drawable │ └── app_icon.xml │ └── values │ ├── colors.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── set-compile-args.gradle ├── settings.gradle ├── studio_versions.properties └── studiow /.gitattributes: -------------------------------------------------------------------------------- 1 | *.jar filter=lfs diff=lfs merge=lfs -text 2 | androidx_prebuilts/** filter=lfs diff=lfs merge=lfs -text 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /studio 13 | /captures 14 | .externalNativeBuild 15 | /androidx_prebuilts -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🎉 DEPRECATED 🎉 2 | 3 | The contents of this repo are no longer needed to play around with Jetpack Compose. You can follow official guides [here](https://developer.android.com/jetpack/compose 4 | 5 | Also feel free to checkout these resources if you interested in Jetpack Compose: 6 | 7 | Android Team created a `#compose` channel on [Kotlin's Slack](https://kotlinlang.slack.com/) to collect feedback from community. Be sure to check it out if you have anything to ask. 8 | 9 | Also, if you speak **Russian**, join our [community](https://t.me/android_declarative) dedicated to declarative UI frameworks for android. 10 | 11 | --- 12 | 13 | ## Try Jetpack Compose now! 14 | 15 | This repository was made to provide a quick dive into what Jetpack Compose feels like. No need to checkout and AOSP and build everything by yourself, main job is done for you. 16 | 17 | ## Installation 18 | 19 | Unfortunately, Jetpack Compose is not published anywhere yet. This repo helps urgent minds to play with Compose by providing all dependencies prebuilt. 20 | 21 | ### Unpack prebuilts 22 | 23 | Download zipped prebuilts from the [latest release](https://github.com/Mishkun/try-compose/releases/latest) and unpack it to project root replacing all the files 24 | 25 | ### Install custom version of Android studio 26 | 27 | Compose needs custom plugins to operate. To use it, you can install custom version of Android Studio provided by wrapper script slightly modified to match this repo files structure. Just launch 28 | 29 | ``` 30 | ./studiow 31 | ``` 32 | 33 | It will download Android Studio from google servers and prompt you to accept license. Type `Y` to proceed. After installing script will open Android Studio within the repo folder to play with. 34 | 35 | ## Use own prebuilts 36 | 37 | If you want to use the most recent Jetpack Compose dependencies and can't wait for me to recompile and publish new release, but have already established project based on this template, you can build Jetpack Compose by yourself and then add the following line to your `local.properties` file 38 | 39 | ``` 40 | androidx.home="path/to/your/androidx/checkout" 41 | ``` 42 | 43 | ## Feedback 44 | 45 | Android Team created a `#compose` channel on [Kotlin's Slack](https://kotlinlang.slack.com/) to collect feedback from community. Be sure to check it out if you have anything to ask. 46 | 47 | Also, if you speak Russian, join our [community](https://t.me/android_declarative) dedicated to declarative UI frameworks for android. 48 | 49 | ## That's all, folks!! 50 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "com.android.application" 2 | 3 | apply plugin: "kotlin-android" 4 | 5 | apply from: '../set-compile-args.gradle' 6 | 7 | repositories { 8 | maven { url "$androidx_home/out/ui/build/support_repo/" } 9 | maven { url "$androidx_home/prebuilts/androidx/external/" } 10 | google() 11 | jcenter() 12 | } 13 | 14 | android { 15 | compileSdkVersion 28 16 | defaultConfig { 17 | applicationId "dev.mishkun.trycompose" 18 | minSdkVersion 21 19 | targetSdkVersion 28 20 | versionCode 1 21 | versionName "1.0" 22 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 23 | } 24 | tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all { 25 | kotlinOptions { 26 | useIR = true 27 | } 28 | } 29 | buildTypes { 30 | release { 31 | minifyEnabled false 32 | proguardFiles getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" 33 | } 34 | } 35 | } 36 | 37 | dependencies { 38 | implementation fileTree(dir: "libs", include: ["*.jar"]) 39 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 40 | implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" 41 | implementation "androidx.appcompat:appcompat:1.0.0" 42 | implementation "androidx.core:core-ktx:1.0.2" 43 | implementation "androidx.compose:compose-runtime:$ui_version" 44 | 45 | implementation "androidx.ui:ui-framework:$ui_version" 46 | implementation "androidx.ui:ui-material:$ui_version" 47 | implementation "androidx.ui:ui-layout:$ui_version" 48 | 49 | testImplementation "junit:junit:4.12" 50 | androidTestImplementation "androidx.test:runner:1.1.1" 51 | androidTestImplementation "androidx.test.espresso:espresso-core:3.1.1" 52 | } 53 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/java/dev/mishkun/trycompose/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package dev.mishkun.trycompose 2 | 3 | import androidx.appcompat.app.AppCompatActivity 4 | import android.os.Bundle 5 | import androidx.compose.* 6 | import androidx.ui.core.setContent 7 | 8 | class MainActivity : AppCompatActivity() { 9 | 10 | override fun onCreate(savedInstanceState: Bundle?) { 11 | super.onCreate(savedInstanceState) 12 | setContent { SimpleComposable() } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/dev/mishkun/trycompose/SimpleComposable.kt: -------------------------------------------------------------------------------- 1 | package dev.mishkun.trycompose 2 | 3 | import androidx.compose.* 4 | import androidx.ui.core.Text 5 | import androidx.ui.material.MaterialTheme 6 | import androidx.ui.material.themeTextStyle 7 | 8 | @Composable 9 | fun SimpleComposable() { 10 | MaterialTheme { 11 | Text(text = "Hello World!", style = +themeTextStyle { h1 }) 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/app_icon.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 11 | 15 | 19 | 23 | 27 | 32 | 37 | 42 | 46 | 50 | 55 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #8BC34A 4 | #689F38 5 | #CDDC39 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | SoundBoard 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | buildscript { 3 | ext.kotlin_version = "1.3.50-compose-20190806" 4 | ext.ui_version = "0.1.0-dev01" 5 | ext.androidx_home = project.properties["androidx.home"] ?: "$projectDir/androidx_prebuilts" 6 | repositories { 7 | maven { url "$androidx_home/out/ui/build/support_repo/" } 8 | maven { url "$androidx_home/prebuilts/androidx/external/" } 9 | mavenLocal() 10 | google() 11 | jcenter() 12 | 13 | } 14 | dependencies { 15 | classpath "com.android.tools.build:gradle:3.4.0" 16 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 17 | // NOTE: Do not place your application dependencies here; they belong 18 | // in the individual module build.gradle files 19 | } 20 | } 21 | 22 | apply plugin: 'idea' 23 | 24 | idea.module { 25 | excludeDirs += file('$projectDir/androidx_prebuilts') 26 | } 27 | 28 | allprojects { 29 | repositories { 30 | mavenLocal() 31 | google() 32 | jcenter() 33 | 34 | } 35 | } 36 | 37 | task clean(type: Delete) { 38 | delete rootProject.buildDir 39 | } 40 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx1536m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app"s APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Automatically convert third-party libraries to use AndroidX 19 | android.enableJetifier=true 20 | # Kotlin code style for this project: "official" or "obsolete": 21 | kotlin.code.style=official 22 | #androidx.home=/path/to/your/androidx 23 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mishkun/try-compose/d25e075fe076067cf163a32b66561220af8a984e/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu May 09 22:39:55 MSK 2019 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : ".*-> \(.*\)$"` 16 | if expr "$link" : "/.*" > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be "true" or "false"). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM"s JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no "java" command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/"/"\\\\""/g;1s/^/"/;\$s/\$/" \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no "java" command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /set-compile-args.gradle: -------------------------------------------------------------------------------- 1 | /** 2 | * this 3 | */ 4 | 5 | afterEvaluate { 6 | project.tasks.findAll { it.name.matches("compile.*Kotlin") } forEach { 7 | it.kotlinOptions.freeCompilerArgs += "-P" 8 | it.kotlinOptions.freeCompilerArgs += 9 | "plugin:androidx.compose.plugins.kotlin:syntax=FCS" 10 | } 11 | } -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ":app" 2 | -------------------------------------------------------------------------------- /studio_versions.properties: -------------------------------------------------------------------------------- 1 | # AGP override for the UI project. Normally we should be using the same version of AGP that is used 2 | # in AndroidX as a whole, but since we are currently using a separate studio build, we sometimes 3 | # end up updating one before the other. If this is specified, both ./studiow and ./gradlew will 4 | # use this version of AGP instead. 5 | # 6 | # If empty, the version of AGP from AndroidX will be used instead. 7 | # 8 | # Example value for this is: 3.5.0-beta05 9 | agp_override=3.5.0-beta05 10 | # Version properties for ./studiow, which should correspond to the version of AGP used either in 11 | # AndroidX, or specified above if overridden. 12 | studio_version=3.5.0.13 13 | idea_major_version=191 14 | idea_minor_version=7479.19.35 15 | studio_build_number=9626933 -------------------------------------------------------------------------------- /studiow: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | set -m 4 | 5 | # This is a wrapper script that runs the specific version of Android Studio that is recommended for developing in this repository. 6 | # (This serves a similar purpose to gradlew) 7 | # 8 | # NOTE: if you are changing this file, consider applying the changes to ../studiow, used for the main AndroidX project. 9 | 10 | 11 | function getPrebuiltStudioZipPath() { 12 | version="$(grep "studio_version=" ${propertiesFile} | sed 's/[^=]*=//')" 13 | ideaMajorVersion="$(grep "idea_major_version=" ${propertiesFile} | sed 's/[^=]*=//')" 14 | buildNumber="$(grep "studio_build_number=" ${propertiesFile} | sed 's/[^=]*=//')" 15 | osName="$1" 16 | if [ "${osName}" == "linux" ]; then 17 | extension="tar.gz" 18 | else 19 | extension="zip" 20 | fi 21 | 22 | echo "${scriptDir}/androidx_prebuilts/androidx/studio/android-studio-ide-${ideaMajorVersion}.${buildNumber}-${osName}.${extension}" 23 | } 24 | 25 | acceptsLicenseAgreement="$1" 26 | scriptDir="$(cd $(dirname $0) && pwd)" 27 | projectDir=$scriptDir 28 | tempDir="${scriptDir}/studio" 29 | function getOsName() { 30 | unameOutput="$(uname)" 31 | osName="" 32 | if [ "${unameOutput}" == "Linux" ]; then 33 | osName="linux" 34 | else 35 | osName="mac" 36 | fi 37 | echo "${osName}" 38 | } 39 | osName="$(getOsName)" 40 | propertiesFile="${scriptDir}/studio_versions.properties" 41 | prebuiltStudioZipPath="$(getPrebuiltStudioZipPath $osName)" 42 | studioDestName="$(basename ${prebuiltStudioZipPath})" 43 | studioUnzippedPath="${tempDir}/${studioDestName}" 44 | studioUnzippedPath="$(echo ${studioUnzippedPath} | sed 's/\.zip$//' | sed 's/\.tar.gz$//')" 45 | 46 | # The version of AGP we should override with - may be empty if we should just use the default 47 | # version specified in AndroidX. See ui/studio_versions.properties. 48 | agp_override="$(grep "agp_override=" ${propertiesFile} | sed 's/[^=]*=//')" 49 | 50 | # Set the env variable if we have a valid version to override with, else noop 51 | GRADLE_PLUGIN_VERSION_OVERRIDE="" 52 | [ ! -z "$agp_override" ] && GRADLE_PLUGIN_VERSION_OVERRIDE="GRADLE_PLUGIN_VERSION=${agp_override}" 53 | 54 | 55 | function error_exit { 56 | echo "$1" >&2 ## Send message to stderr. 57 | exit 1 58 | } 59 | 60 | function downloadFile() { 61 | fromUrl="$1" 62 | destPath="$2" 63 | tempPath="${destPath}.tmp" 64 | if [ -f "${destPath}" ]; then 65 | read -r -n 1 -p "File already exists. Do you want to delete and re-download? [Y/n]? " reply 66 | 67 | if [ ! -z "${reply}" ]; then 68 | # Fix missing newline 69 | echo 70 | fi 71 | 72 | case "${reply}" in 73 | [yY]|"") 74 | rm "${destPath}" 75 | ;; 76 | *) 77 | esac 78 | fi 79 | 80 | if [ -f "${destPath}" ]; then 81 | echo "Using existing file from ${destPath}" 82 | else 83 | echo "Downloading ${fromUrl} to ${destPath}" 84 | curl "${fromUrl}" > "${tempPath}" 85 | mv "${tempPath}" "${destPath}" 86 | fi 87 | } 88 | 89 | function findStudioMacAppPath() { 90 | echo "$(find "${studioUnzippedPath}" -type d -depth 1 -name "Android Studio*.app")" 91 | } 92 | 93 | function getLicensePath() { 94 | if [ "${osName}" == "mac" ]; then 95 | appPath="$(findStudioMacAppPath)" 96 | echo "${appPath}/Contents/Resources/LICENSE.txt" 97 | else 98 | echo "${studioUnzippedPath}/android-studio/LICENSE.txt" 99 | fi 100 | } 101 | 102 | function checkLicenseAgreement() { 103 | # TODO: Is there a more official way to check that the user accepts the license? 104 | 105 | licenseAcceptedPath="${studioUnzippedPath}/STUDIOW_LICENSE_ACCEPTED" 106 | 107 | if [ ! -f "${licenseAcceptedPath}" ]; then 108 | if [ "${acceptsLicenseAgreement}" == "-y" ]; then 109 | touch "${licenseAcceptedPath}" 110 | else 111 | read -r -n 1 -p "Do you accept the license agreement at $(getLicensePath) [Y/n]? " reply 112 | 113 | if [ ! -z "${reply}" ]; then 114 | # Fix missing newline 115 | echo 116 | fi 117 | 118 | case "${reply}" in 119 | [yY]|"") 120 | touch "${licenseAcceptedPath}" 121 | ;; 122 | *) 123 | exit 1 124 | ;; 125 | esac 126 | fi 127 | fi 128 | } 129 | 130 | # Temporary fix. Remove this after fixing b/135183535 131 | function updateJvmHeapSize() { 132 | if [ "${osName}" == "mac" ]; then 133 | sed -i '' 's/-Xmx.*/-Xmx8g/' "$(findStudioMacAppPath)/Contents/bin/studio.vmoptions" 134 | else 135 | sed -i 's/-Xmx.*/-Xmx8g/' "${studioUnzippedPath}/android-studio/bin/studio64.vmoptions" 136 | sed -i 's/-Xmx.*/-Xmx4g/' "${studioUnzippedPath}/android-studio/bin/studio.vmoptions" 137 | fi 138 | } 139 | 140 | function updateStudio() { 141 | # skip if already up-to-date 142 | if stat "${studioUnzippedPath}" >/dev/null 2>/dev/null; then 143 | # already up-to-date 144 | return 145 | fi 146 | 147 | mkdir -p "${tempDir}" 148 | 149 | echo "Removing previous installations" 150 | ls "${tempDir}" | grep -v "^${studioDestName}\$" | sed "s|^|${tempDir}/|" | xargs rm -rf 151 | 152 | echo "Unzipping" 153 | if [ "${osName}" == "linux" ]; then 154 | mkdir $studioUnzippedPath 155 | tar -xzf "${prebuiltStudioZipPath}" --directory "${studioUnzippedPath}" 156 | else 157 | unzip "${prebuiltStudioZipPath}" -d "${studioUnzippedPath}" 158 | fi 159 | } 160 | 161 | # Copies the built compose-ide-plugin to the plugin directory of the studio installation. This 162 | # ensures that the compose plugin is used at startup 163 | function updateComposeIdePlugin() { 164 | if [ "${osName}" == "mac" ]; then 165 | composeIdePluginDirectory="$(findStudioMacAppPath)/Contents/plugins/compose-ide-plugin/" 166 | else 167 | composeIdePluginDirectory="${studioUnzippedPath}/android-studio/plugins/" 168 | fi 169 | # this is the idea sandbox directory that the compose ide plugin is located in 170 | composePluginDirectory="${projectDir}/androidx_prebuilts/out/ui/compose/compose-ide-plugin/build/idea-sandbox/plugins/compose-ide-plugin/" 171 | 172 | echo "" 173 | echo "Copying compose-ide-plugin to $composeIdePluginDirectory" 174 | echo "" 175 | mkdir -p "${composeIdePluginDirectory}" 176 | cp -f -R "${composePluginDirectory}" "${composeIdePluginDirectory}" 177 | } 178 | 179 | function ensureCompose() { 180 | # This gradle command will prepare a sandbox directory that we can point studio to that will 181 | # have all of the correct structure to load the compose plugin 182 | ${scriptDir}/gradlew -p ${projectDir} :compose:compose-ide-plugin:prepareSandbox 183 | } 184 | 185 | # ANDROID_LINT_NULLNESS_IGNORE_DEPRECATED environment variable prevents Studio from showing IDE 186 | # inspection warnings for nullability issues, if the context is deprecated 187 | # This environment variable is consumed by InteroperabilityDetector.kt 188 | 189 | function runStudioLinux() { 190 | studioPath="${studioUnzippedPath}/android-studio/bin/studio.sh" 191 | updateComposeIdePlugin 192 | 193 | echo "" 194 | echo "Launching Studio" 195 | # Override AGP version overridden because compose studio is behind androidx studio 196 | env STUDIO_PROPERTIES="${projectDir}/idea.properties" \ 197 | STUDIO_VM_OPTIONS="${projectDir}/../development/studio/studio.vmoptions" \ 198 | ANDROID_LINT_NULLNESS_IGNORE_DEPRECATED="true" \ 199 | KOTLIN_OVERRIDE="1.3.50-compose-20190806" \ 200 | $GRADLE_PLUGIN_VERSION_OVERRIDE \ 201 | "${studioPath}" "${projectDir}" & 202 | } 203 | 204 | function runStudioMac() { 205 | appPath="$(findStudioMacAppPath)" 206 | updateComposeIdePlugin 207 | 208 | echo "" 209 | echo "Launching Studio" 210 | # Override AGP version overridden because compose studio is behind androidx studio 211 | env STUDIO_PROPERTIES="${projectDir}/idea.properties" \ 212 | STUDIO_VM_OPTIONS="${projectDir}/../development/studio/studio.vmoptions" \ 213 | ANDROID_LINT_NULLNESS_IGNORE_DEPRECATED="true" \ 214 | KOTLIN_OVERRIDE="1.3.50-compose-20190806" \ 215 | $GRADLE_PLUGIN_VERSION_OVERRIDE \ 216 | open -a "${appPath}" "${projectDir}" 217 | } 218 | 219 | function runStudio() { 220 | updateJvmHeapSize 221 | if [ "${osName}" == "mac" ]; then 222 | runStudioMac 223 | else 224 | runStudioLinux 225 | fi 226 | } 227 | 228 | function main() { 229 | updateStudio 230 | ensureCompose 231 | checkLicenseAgreement 232 | runStudio 233 | } 234 | 235 | main 236 | --------------------------------------------------------------------------------