• 0

Problems building a cordova android app on mac


Question

+unabatedshagie

I'm having problems getting my Cordova app to build on my Mac running El Capitan.

I've downloaded and installed JDK-8u73-macosx-x64.dmg and android-studio-ide-141.2456560-mac.dmg which seem like they are the latest versions available.

I've ran Android studio and got it to download the Android SDK (basically whatever's checked to install by default)

I've also installed Ant via Homebrew (brew install ant)

  • Ant is installed at /usr/local/bin/ant
  • Java is installed at /usr/bin/java
  • Android SDK is installed at /Users/admin/Library/Android/sdk

I've created a .bash_profile file at ~/.bash_profile which contains the following:

# JAVA
export JAVA_HOME=$(/usr/libexec/java_home)

# ANT
export ANT_HOME=$(/usr/local/bin/ant)

# Export to PATH
export PATH=${PATH}:${JAVA_HOME}/bin:${ANT_HOME}/bin

When I run cordova build android I get the following error:

admins-Mac-mini:Swipii admin$ cordova build android
ANDROID_HOME=/Users/admin/Library/Android/sdk
JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_73.jdk/Contents/Home
Failed to notify ProjectEvaluationListener.afterEvaluate(), but primary configuration failure takes precedence.
java.lang.IllegalStateException: buildToolsVersion is not specified.
    at com.google.common.base.Preconditions.checkState(Preconditions.java:176)
    at com.android.build.gradle.BasePlugin.createAndroidTasks(BasePlugin.java:599)
    at com.android.build.gradle.BasePlugin$10$1.call(BasePlugin.java:566)
    at com.android.build.gradle.BasePlugin$10$1.call(BasePlugin.java:563)
    at com.android.builder.profile.ThreadRecorder$1.record(ThreadRecorder.java:55)
    at com.android.builder.profile.ThreadRecorder$1.record(ThreadRecorder.java:47)
    at com.android.build.gradle.BasePlugin$10.execute(BasePlugin.java:562)
    at com.android.build.gradle.BasePlugin$10.execute(BasePlugin.java:559)
    at org.gradle.listener.BroadcastDispatch$ActionInvocationHandler.dispatch(BroadcastDispatch.java:109)
    at org.gradle.listener.BroadcastDispatch$ActionInvocationHandler.dispatch(BroadcastDispatch.java:98)
    at org.gradle.listener.BroadcastDispatch.dispatch(BroadcastDispatch.java:83)
    at org.gradle.listener.BroadcastDispatch.dispatch(BroadcastDispatch.java:31)
    at org.gradle.messaging.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
    at com.sun.proxy.$Proxy12.afterEvaluate(Unknown Source)
    at org.gradle.configuration.project.LifecycleProjectEvaluator.notifyAfterEvaluate(LifecycleProjectEvaluator.java:79)
    at org.gradle.configuration.project.LifecycleProjectEvaluator.evaluate(LifecycleProjectEvaluator.java:65)
    at org.gradle.api.internal.project.AbstractProject.evaluate(AbstractProject.java:504)
    at org.gradle.api.internal.project.AbstractProject.evaluate(AbstractProject.java:83)
    at org.gradle.execution.TaskPathProjectEvaluator.configureHierarchy(TaskPathProjectEvaluator.java:42)
    at org.gradle.configuration.DefaultBuildConfigurer.configure(DefaultBuildConfigurer.java:35)
    at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:129)
    at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:106)
    at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:86)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter$DefaultBuildController.run(InProcessBuildActionExecuter.java:80)
    at org.gradle.launcher.cli.ExecuteBuildAction.run(ExecuteBuildAction.java:33)
    at org.gradle.launcher.cli.ExecuteBuildAction.run(ExecuteBuildAction.java:24)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:36)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:26)
    at org.gradle.launcher.daemon.server.exec.ExecuteBuild.doBuild(ExecuteBuild.java:47)
    at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:34)
    at org.gradle.launcher.daemon.server.exec.DaemonCommandExecution.proceed(DaemonCommandExecution.java:119)
    at org.gradle.launcher.daemon.server.exec.WatchForDisconnection.execute(WatchForDisconnection.java:35)
    at org.gradle.launcher.daemon.server.exec.DaemonCommandExecution.proceed(DaemonCommandExecution.java:119)
    at org.gradle.launcher.daemon.server.exec.ResetDeprecationLogger.execute(ResetDeprecationLogger.java:24)
    at org.gradle.launcher.daemon.server.exec.DaemonCommandExecution.proceed(DaemonCommandExecution.java:119)
    at org.gradle.launcher.daemon.server.exec.StartStopIfBuildAndStop.execute(StartStopIfBuildAndStop.java:33)
    at org.gradle.launcher.daemon.server.exec.DaemonCommandExecution.proceed(DaemonCommandExecution.java:119)
    at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:71)
    at org.gradle.launcher.daemon.server.exec.ForwardClientInput$2.call(ForwardClientInput.java:69)
    at org.gradle.util.Swapper.swap(Swapper.java:38)
    at org.gradle.launcher.daemon.server.exec.ForwardClientInput.execute(ForwardClientInput.java:69)
    at org.gradle.launcher.daemon.server.exec.DaemonCommandExecution.proceed(DaemonCommandExecution.java:119)
    at org.gradle.launcher.daemon.server.exec.LogToClient.doBuild(LogToClient.java:60)
    at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:34)
    at org.gradle.launcher.daemon.server.exec.DaemonCommandExecution.proceed(DaemonCommandExecution.java:119)
    at org.gradle.launcher.daemon.server.exec.EstablishBuildEnvironment.doBuild(EstablishBuildEnvironment.java:70)
    at org.gradle.launcher.daemon.server.exec.BuildCommandOnly.execute(BuildCommandOnly.java:34)
    at org.gradle.launcher.daemon.server.exec.DaemonCommandExecution.proceed(DaemonCommandExecution.java:119)
    at org.gradle.launcher.daemon.server.exec.DaemonHygieneAction.execute(DaemonHygieneAction.java:39)
    at org.gradle.launcher.daemon.server.exec.DaemonCommandExecution.proceed(DaemonCommandExecution.java:119)
    at org.gradle.launcher.daemon.server.exec.StartBuildOrRespondWithBusy$1.run(StartBuildOrRespondWithBusy.java:46)
    at org.gradle.launcher.daemon.server.DaemonStateCoordinator$1.run(DaemonStateCoordinator.java:246)
    at org.gradle.internal.concurrent.DefaultExecutorFactory$StoppableExecutorImpl$1.run(DefaultExecutorFactory.java:64)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

FAILURE: Build failed with an exception.

* Where:
Script '/Users/admin/Documents/Swipii/platforms/android/CordovaLib/cordova.gradle' line: 128

* What went wrong:
A problem occurred evaluating root project 'android'.
> No match found

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

BUILD FAILED

Total time: 2.385 secs
ERROR building one of the platforms: Error code 1 for command: /Users/admin/Documents/Swipii/platforms/android/gradlew with args: cdvBuildDebug,-b,/Users/admin/Documents/Swipii/platforms/android/build.gradle,-Dorg.gradle.daemon=true,-Pandroid.useDeprecatedNdk=true
You may not have the required environment or OS to build this project
Error: Error code 1 for command: /Users/admin/Documents/Swipii/platforms/android/gradlew with args: cdvBuildDebug,-b,/Users/admin/Documents/Swipii/platforms/android/build.gradle,-Dorg.gradle.daemon=true,-Pandroid.useDeprecatedNdk=true
admins-Mac-mini:Swipii admin$

I think my .bash_profile file isn't correct but not sure why?

Could someone point me in the right direction?

Link to post
Share on other sites

5 answers to this question

Recommended Posts

  • 0
simplezz

You're missing the build tools. Android uses the Gradle build system by default now. In the SDK manager, check the build tools option to install it. For example, here's mine:

X4kGx2i.png

Link to post
Share on other sites
  • 0
+unabatedshagie

I've got all those installed already.

Link to post
Share on other sites
  • 0
simplezz

You need to paste your build.gradle file. It sounds like you haven't specified the buildToolsVersion. For example:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.2"

    defaultConfig {
        applicationId "com.tacit.estocks"
        minSdkVersion 21
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFile 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.1.1'
    compile 'com.android.support:design:23.1.1'
}

What version do you have written there and does it match the installed version?

Link to post
Share on other sites
  • 0
+unabatedshagie

I'm not 100% sure how all this works on the Android side.

 

I've got everything working on the iOS side, I had just assumed that I could add the android platform to cordova and build it like I did with iOS after I had Java and the Android SDK installed.

 

My build.gradle file looks like this:

 

/*
       Licensed to the Apache Software Foundation (ASF) under one
       or more contributor license agreements.  See the NOTICE file
       distributed with this work for additional information
       regarding copyright ownership.  The ASF licenses this file
       to you under the Apache License, Version 2.0 (the
       "License"); you may not use this file except in compliance
       with the License.  You may obtain a copy of the License at

         http://www.apache.org/licenses/LICENSE-2.0

       Unless required by applicable law or agreed to in writing,
       software distributed under the License is distributed on an
       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
       KIND, either express or implied.  See the License for the
       specific language governing permissions and limitations
       under the License.
*/

// GENERATED FILE! DO NOT EDIT!

apply plugin: 'android'

buildscript {
    repositories {
        mavenCentral()
    }

    // Switch the Android Gradle plugin version requirement depending on the
    // installed version of Gradle. This dependency is documented at
    // http://tools.android.com/tech-docs/new-build-system/version-compatibility
    // and https://issues.apache.org/jira/browse/CB-8143
    dependencies {
        classpath 'com.android.tools.build:gradle:1.5.0'
    }
   }

// Allow plugins to declare Maven dependencies via build-extras.gradle.
repositories {
    mavenCentral()
}

task wrapper(type: Wrapper) {
    gradleVersion = '2.8'
}

// Configuration properties. Set these via environment variables, build-extras.gradle, or gradle.properties.
// Refer to: http://www.gradle.org/docs/current/userguide/tutorial_this_and_that.html
ext {
    apply from: 'CordovaLib/cordova.gradle'
    // The value for android.compileSdkVersion.
    if (!project.hasProperty('cdvCompileSdkVersion')) {
        cdvCompileSdkVersion = null;
    }
    // The value for android.buildToolsVersion.
    if (!project.hasProperty('cdvBuildToolsVersion')) {
        cdvBuildToolsVersion = null;
    }
    // Sets the versionCode to the given value.
    if (!project.hasProperty('cdvVersionCode')) {
        cdvVersionCode = null
    }
    // Sets the minSdkVersion to the given value.
    if (!project.hasProperty('cdvMinSdkVersion')) {
        cdvMinSdkVersion = null
    }
    // Whether to build architecture-specific APKs.
    if (!project.hasProperty('cdvBuildMultipleApks')) {
        cdvBuildMultipleApks = null
    }
    // .properties files to use for release signing.
    if (!project.hasProperty('cdvReleaseSigningPropertiesFile')) {
        cdvReleaseSigningPropertiesFile = null
    }
    // .properties files to use for debug signing.
    if (!project.hasProperty('cdvDebugSigningPropertiesFile')) {
        cdvDebugSigningPropertiesFile = null
    }
    // Set by build.js script.
    if (!project.hasProperty('cdvBuildArch')) {
        cdvBuildArch = null
    }

    // Plugin gradle extensions can append to this to have code run at the end.
    cdvPluginPostBuildExtras = []
}

// PLUGIN GRADLE EXTENSIONS START
// PLUGIN GRADLE EXTENSIONS END

def hasBuildExtras = file('build-extras.gradle').exists()
if (hasBuildExtras) {
    apply from: 'build-extras.gradle'
}

// Set property defaults after extension .gradle files.
if (ext.cdvCompileSdkVersion == null) {
    ext.cdvCompileSdkVersion = privateHelpers.getProjectTarget()
}
if (ext.cdvBuildToolsVersion == null) {
    ext.cdvBuildToolsVersion = privateHelpers.findLatestInstalledBuildTools()
}
if (ext.cdvDebugSigningPropertiesFile == null && file('debug-signing.properties').exists()) {
    ext.cdvDebugSigningPropertiesFile = 'debug-signing.properties'
}
if (ext.cdvReleaseSigningPropertiesFile == null && file('release-signing.properties').exists()) {
    ext.cdvReleaseSigningPropertiesFile = 'release-signing.properties'
}

// Cast to appropriate types.
ext.cdvBuildMultipleApks = cdvBuildMultipleApks == null ? false : cdvBuildMultipleApks.toBoolean();
ext.cdvMinSdkVersion = cdvMinSdkVersion == null ? null : Integer.parseInt('' + cdvMinSdkVersion)
ext.cdvVersionCode = cdvVersionCode == null ? null : Integer.parseInt('' + cdvVersionCode)

def computeBuildTargetName(debugBuild) {
    def ret = 'assemble'
    if (cdvBuildMultipleApks && cdvBuildArch) {
        def arch = cdvBuildArch == 'arm' ? 'armv7' : cdvBuildArch
        ret += '' + arch.toUpperCase().charAt(0) + arch.substring(1);
    }
    return ret + (debugBuild ? 'Debug' : 'Release')
}

// Make cdvBuild a task that depends on the debug/arch-sepecific task.
task cdvBuildDebug
cdvBuildDebug.dependsOn {
    return computeBuildTargetName(true)
}

task cdvBuildRelease
cdvBuildRelease.dependsOn {
    return computeBuildTargetName(false)
}

task cdvPrintProps << {
    println('cdvCompileSdkVersion=' + cdvCompileSdkVersion)
    println('cdvBuildToolsVersion=' + cdvBuildToolsVersion)
    println('cdvVersionCode=' + cdvVersionCode)
    println('cdvMinSdkVersion=' + cdvMinSdkVersion)
    println('cdvBuildMultipleApks=' + cdvBuildMultipleApks)
    println('cdvReleaseSigningPropertiesFile=' + cdvReleaseSigningPropertiesFile)
    println('cdvDebugSigningPropertiesFile=' + cdvDebugSigningPropertiesFile)
    println('cdvBuildArch=' + cdvBuildArch)
    println('computedVersionCode=' + android.defaultConfig.versionCode)
    android.productFlavors.each { flavor ->
        println('computed' + flavor.name.capitalize() + 'VersionCode=' + flavor.versionCode)
    }
}

android {
    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            resources.srcDirs = ['src']
            aidl.srcDirs = ['src']
            renderscript.srcDirs = ['src']
            res.srcDirs = ['res']
            assets.srcDirs = ['assets']
            jniLibs.srcDirs = ['libs']
        }
    }

    defaultConfig {
        versionCode cdvVersionCode ?: Integer.parseInt("" + privateHelpers.extractIntFromManifest("versionCode") + "0")
        applicationId privateHelpers.extractStringFromManifest("package")

        if (cdvMinSdkVersion != null) {
            minSdkVersion cdvMinSdkVersion
        }
    }

    lintOptions {
      abortOnError false;
    }

    compileSdkVersion cdvCompileSdkVersion
    buildToolsVersion cdvBuildToolsVersion

    if (Boolean.valueOf(cdvBuildMultipleApks)) {
        productFlavors {
            armv7 {
                versionCode defaultConfig.versionCode + 2
                ndk {
                    abiFilters "armeabi-v7a", ""
                }
            }
            x86 {
                versionCode defaultConfig.versionCode + 4
                ndk {
                    abiFilters "x86", ""
                }
            }
            all {
                ndk {
                    abiFilters "all", ""
                }
            }
        }
    } else if (!cdvVersionCode) {
      def minSdkVersion = cdvMinSdkVersion ?: privateHelpers.extractIntFromManifest("minSdkVersion")
      // Vary versionCode by the two most common API levels:
      // 14 is ICS, which is the lowest API level for many apps.
      // 20 is Lollipop, which is the lowest API level for the updatable system webview.
      if (minSdkVersion >= 20) {
        defaultConfig.versionCode += 9
      } else if (minSdkVersion >= 14) {
        defaultConfig.versionCode += 8
      }
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_6
        targetCompatibility JavaVersion.VERSION_1_6
    }

    if (cdvReleaseSigningPropertiesFile) {
        signingConfigs {
            release {
                // These must be set or Gradle will complain (even if they are overridden).
                keyAlias = ""
                keyPassword = "__unset" // And these must be set to non-empty in order to have the signing step added to the task graph.
                storeFile = null
                storePassword = "__unset"
            }
        }
        buildTypes {
            release {
                signingConfig signingConfigs.release
            }
        }
        addSigningProps(cdvReleaseSigningPropertiesFile, signingConfigs.release)
    }
    if (cdvDebugSigningPropertiesFile) {
        addSigningProps(cdvDebugSigningPropertiesFile, signingConfigs.debug)
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: '*.jar')
    // SUB-PROJECT DEPENDENCIES START
    debugCompile project(path: "CordovaLib", configuration: "debug")
    releaseCompile project(path: "CordovaLib", configuration: "release")
    compile "com.facebook.android:facebook-android-sdk:4.+"
    // SUB-PROJECT DEPENDENCIES END
}

def promptForReleaseKeyPassword() {
    if (!cdvReleaseSigningPropertiesFile) {
        return;
    }
    if ('__unset'.equals(android.signingConfigs.release.storePassword)) {
        android.signingConfigs.release.storePassword = privateHelpers.promptForPassword('Enter key store password: ')
    }
    if ('__unset'.equals(android.signingConfigs.release.keyPassword)) {
        android.signingConfigs.release.keyPassword = privateHelpers.promptForPassword('Enter key password: ');
    }
}

gradle.taskGraph.whenReady { taskGraph ->
    taskGraph.getAllTasks().each() { task ->
        if (task.name == 'validateReleaseSigning') {
            promptForReleaseKeyPassword()
        }
    }
}

def addSigningProps(propsFilePath, signingConfig) {
    def propsFile = file(propsFilePath)
    def props = new Properties()
    propsFile.withReader { reader ->
        props.load(reader)
    }

    def storeFile = new File(props.get('key.store') ?: privateHelpers.ensureValueExists(propsFilePath, props, 'storeFile'))
    if (!storeFile.isAbsolute()) {
        storeFile = RelativePath.parse(true, storeFile.toString()).getFile(propsFile.getParentFile())
    }
    if (!storeFile.exists()) {
        throw new FileNotFoundException('Keystore file does not exist: ' + storeFile.getAbsolutePath())
    }
    signingConfig.keyAlias = props.get('key.alias') ?: privateHelpers.ensureValueExists(propsFilePath, props, 'keyAlias')
    signingConfig.keyPassword = props.get('keyPassword', props.get('key.alias.password', signingConfig.keyPassword))
    signingConfig.storeFile = storeFile
    signingConfig.storePassword = props.get('storePassword', props.get('key.store.password', signingConfig.storePassword))
    def storeType = props.get('storeType', props.get('key.store.type', ''))
    if (!storeType) {
        def filename = storeFile.getName().toLowerCase();
        if (filename.endsWith('.p12') || filename.endsWith('.pfx')) {
            storeType = 'pkcs12'
        } else {
            storeType = signingConfig.storeType // "jks"
        }
    }
    signingConfig.storeType = storeType
}

for (def func : cdvPluginPostBuildExtras) {
    func()
}

// This can be defined within build-extras.gradle as:
//     ext.postBuildExtras = { ... code here ... }
if (hasProperty('postBuildExtras')) {
    postBuildExtras()
}

 

Link to post
Share on other sites
  • 0
simplezz

Well, the error log clearly states that the buildToolsVersion variable isn't defined.

Quote

java.lang.IllegalStateException: buildToolsVersion is not specified.

That script you posted appears to look in

CordovaLib/cordova.gradle

For the defaults. If it can't find one, it then goes off to look for one via

xt.cdvBuildToolsVersion = privateHelpers.findLatestInstalledBuildTools()

Unless there's a problem with how your directories/environmental variables are setup, I'd guess that you need to manually specify the buildToolsVersion in 'cordova.gradle' because it doesn't seem to be finding it itself. When I update my build tools, I always manually update build.gradle.

Link to post
Share on other sites
This topic is now closed to further replies.
  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By Usama Jawad96
      Android 12 Developer Preview 3 is out now for Pixel devices
      by Usama Jawad

      Google announced Android 12 back in February and released the first developer preview in the same month. Over time, it has released other developer previews too, each containing bug fixes and enhancements to the overall experience. Now, the company has rolled out Android 12 Developer Preview 3 for Pixel devices and it gears up for its first Beta launch next month.

      Starting off with what's new in this release, we have improved app launch experiences. All apps will now launch with a a splash screen showing the app icon before transitioning to the actual app. Google hopes to bring consistency in design across apps with this change but has allowed developers to customize the experience using the SplashScreen API.

      Similarly, there's a new template for call notifications in order to enhance visibility and to bring them in line with other notification components. Developers with apps which make use of dialer capabilities can take advantage of the CallStyle template to create notifications.

      For apps that utilize exact alarms which bypass Doze and App Standby restrictions, Google has added a new permission that developers can include in their app manifest. However, users will also have visibility over this setting and can choose to disable it for specific apps. Google has also cautioned that it is better if developers move away from exact alarms where possible because they can cause a lot of battery drain if not used correctly.

      Web linking is being improved in this release too. Essentially, web links that aren't approved manually by the user will open in the default web browser, rather than the user being given an option of how they want to open a link. Developers who want the links from their domain to open directly within their app are advised to make use of App Links to enable this behavior.

      With this preview release, Google has also introduced richer haptic experiences that developers can utilize in the UI elements of their games. The company says that it will be collaborating with other OEMs "to bring the latest in haptics support to users across the ecosystem".

      Over on the non-user facing side of things, we already know that Google is deprecating RenderScript in favor of Vulkan. Android 12 Developer Preview 3 also comes with an improved video encoding experience by standardizing keys for controlling video Quantization Parameters (QP).

      The company has also noted that many OEMs include custom camera effects such as bokeh and HDR, and with the latest Android release, these will be exposed to the platform via the CameraX library. If a vendor does not provide an implementation of an effect, apps will default to the CameraX implementation of the same effect. This will enable apps to make use of these custom extensions without too many changes to the code.

      Quad camera setups with extremely high resolution sensors are becoming quite common so Google has also introduced new platform APIs that enable apps to take advantage of specific sensors. On the machine learning (ML) side of things, the Neural Network API and ML accelerators have been enhanced to reduce overheads, and has also decoupled it from platform releases.

      Better diagnostics for native app crashes are also included in this release by giving apps access to crash dump files for granular debugging. Lastly, more flexibility is being given to backup configurations too. Google says that:

      In terms of timelines, Google has highlighted that with Android 12's release cadence, it is prioritizing app compatibility. With the first Beta update expected next month, it recommends that you gear up for compatibility testing so by the time the operating system reaches Platform Stability in August 2021 and all SDKs and APIs are finalized, you are ready with a compatible version of your app.

      Android 12 Developer Preview 3 is available right now on Pixel 3/3 XL, Pixel 3a/3a XL, Pixel 4/4 XL, Pixel 4a/4a 5G, and Pixel 5. If you've already installed a developer preview release before, you'll receive the update automatically over-the-air (OTA). However, if you don't have a preview build on your device, you will need to flash it manually. Find out how to do so in our detailed guide here.

    • By hellowalkman
      Android 12 may auto-hibernate your unused apps to free up storage
      by Sayan Sen

      With Android 11, Google introduced a feature that would automatically revoke permissions of unused apps. Now with its next major upgrade in Android 12, Google may expand upon that feature and automatically hibernate those apps according to a report by XDA. Not only that but "temporary files", which probably indicate cache files, compilation artifacts and such, of those unused apps, might be removed to free storage space. Back in January, XDA had spotted a couple of new commits to the Android Open Source Project (AOSP) Gerrit which hinted that developers were working on such a feature.

      In this build that was tested by XDA, one has to enable the "Remove permissions and free up space" option in the "Unused apps" section. The option was present in the "App info" for every installed app. The images below from left to right show the steps.







      While the auto-hibernate and space-saving features are interesting and would certainly prove helpful, especially to Android users on budget phones with low storage, or as a battery-saving utility in general, there is no way to know if they will end up in the final build.

      Source and images: XDA

    • By Jay Bonggolto
      Motorola to release Moto G60 and Moto G40 Fusion on April 20 in India
      by Jay Bonggolto

      It has been quite some time since Motorola last introduced a smartphone in India. The company launched the Moto G9 in the country in August 2020 for ₹11,499, featuring a Snapdragon 662 SoC, 48MP camera, and a 5,000mAh battery with 20W fast charging support, among other features.

      Later this month, Motorola is set to unveil two new devices in India as part of its G series. The new phones are the Moto G40 Fusion and Moto G60, which the firm teased today on its Instagram account. The handsets will be officially announced on April 20 in India.

      Prior to the official unveiling, Motorola spilled the beans on some of the key specs of these handsets. The G40 Fusion is apparently the basic model between the two with 64MP triple camera. On the other hand, the G60 features a 108MP camera. That said, they have the same camera design on the back.



      Both smartphones are powered by Qualcomm's Snapdragon 732G SoC, a chipset often associated with improved gaming experience. Both devices also have the same display. The G60 and G40 Fusion sport a 6.8-inch display with support for HDR10 and 120Hz refresh rate. There's also a punch-hole cutout on the screen for the selfie camera.

      Motorola's teaser didn't mention anything about the phones' prices yet. The devices will be available to purchase via Flipkart.

    • By Jay Bonggolto
      Microsoft Edge Canary is now available on Android with a new UI update
      by Jay Bonggolto

      Microsoft has quietly rolled out Edge Canary on Android with a fresh user interface, among other changes. The browser's Canary channel runs version 91 and it introduces a host of features such as access to experimental flags.

      The latest build has version number 91.0.858.0 and Microsoft promises to release new builds every day. The Canary build was first spotted by a Reddit user and picked up by Aggiornamenti Lumia.

      It's worth noting that Edge Canary on Android has a similar user experience and shell as the regular Edge browser for mobile. For example, it has the same page layout options as the regular Edge. However, the Canary channel does not have the option to view your reading list. It also has a different menu layout compared to the existing Edge mobile browser.

      Today's release doesn't entirely come as a surprise seeing as the software giant announced last month that it planned to transition to a common codebase for the desktop, Android, and iOS versions later this year to streamline the development of any new features. The way things are at present, this task needs to be done three times due to the different codebases for Android, iOS, and the desktop.

      If you want to try out the preview channel for Edge on Android, it is now available to download via the Google Play Store.

    • By Namerah S
      Sony Xperia 1 III and Xperia 5 III price revealed on Sony Russia website
      by Namerah Saud Fatmi

      In a launch event that was live-streamed on YouTube yesterday, Sony announced its latest trio of smartphones under the Xperia branding. The Japanese conglomerate unveiled the Xperia 1 III, Xperia 5 III, and Xperia 10 III.

      Almost all the key specifications of the three smartphones were unveiled yesterday. However, Sony chose not to share the exact launch dates and prices of the Xperia devices. Thanks to two new listings on Sony Russia's online store, spotted by Android Authority, the Russian prices are now known. These are likely to be similar in other parts of the world such as the U.S., giving people approximate figures for the phones once they launch in those places as well.

      As seen on Sony.ru, the Xperia 1 III boasting a 6.5-inch 4K HDR OLED display with a 120Hz refresh rate, 21:9 aspect ratio and Gorilla Glass Victus is priced at 99,990 RUB ($1,313.31). The device also features the Snapdragon 888 5G chipset, a 4500mAh with 30W fast-charging, and a quad-camera setup that includes a variable telephoto lens paired with a dual PD sensor.

      Meanwhile, the Xperia 5 III is selling for RUB 84,990 ($1,116.29) on the Russian site. The second Xperia device features a 6.1-inch 21:9 HDR 120Hz OLED display with a 21:9 aspect ratio and Gorilla Glass 6. It uses the same SoC as the Xperia 1 III, the SD 888 5G chip, and also has a 4500mAh with 30W fast-charging. Both smartphones have IPX5 and IP X8 waterproof certifications paired with IP6X dustproof ratings.

      Pre-orders for the two smartphones are currently open on Sony Russia's online store. As for the launch date, Sony Russia has teased launch promotion on its official Instagram handle, revealing Russian release dates and pre-order bonuses for the region.

      As seen in the promo banners shared by Sony Russia on the social media platform, the Xperia 1 III is set to arrive on July 20 while the Xperia 5 III is scheduled to launch on August 3. Both Xperia products will ship with a pair of Sony WF-XB700 true wireless earbuds as a pre-purchase bonus.