Friday, October 26, 2018

Prevent WebView.loadUrl() to open system browser

It's a simple example to load my a web page in WebView.

package com.blogspot.android_er.myapplicationwebview;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.webkit.WebView;
import android.webkit.WebViewClient;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        WebView myWebView = findViewById(R.id.webview);
        myWebView.getSettings().setJavaScriptEnabled(true);
        myWebView.loadUrl("http://android-er.blogspot.com/");
    }
}


But, when the  myWebView.loadUrl("http://android-er.blogspot.com/") run, the app ask to load in system browser, not the in my WebView.

To solve it (work for me), set WebViewClient before loadUrl.

package com.blogspot.android_er.myapplicationwebview;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.webkit.WebView;
import android.webkit.WebViewClient;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        WebView myWebView = findViewById(R.id.webview);
        myWebView.getSettings().setJavaScriptEnabled(true);

        myWebView.setWebViewClient(new WebViewClient());

        myWebView.loadUrl("http://android-er.blogspot.com/");
    }
}



Layout XML
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="android-er.blogspot.com"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <WebView
        android:id="@+id/webview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />

</LinearLayout>

uses-permission of "android.permission.INTERNET" is need to load from internet.

Google will discontinue support for Nearby Notifications, on December 6th, 2018.

Due to significant increase in irrelevant and spammy notifications that were leading to a poor user experience for Android, Google have decided to discontinue support for Nearby Notifications. Nearby Notifications will be stopped on December 6th, 2018.

source: Android Developers Blog: Discontinuing support for Android Nearby Notifications


Monday, October 22, 2018

How Google Super Res Zoom in Pixel 3 improve Digital zoom

Traditionally, mobile device cameras uses software algorithms to implement digital zoom. Compare with the optical zoom capabilities of DSLR cameras, the quality of digitally zoomed images has not been competitive.

The Super Res Zoom technology in new released Pixel 3 is different and better than any previous digital zoom technique based on upscaling a crop of a single image, because it merge many frames directly onto a higher resolution picture.

This post (from Google AI Blog) explain Super Res Zoom algorithms in details:
See Better and Further with Super Res Zoom on the Pixel 3


Friday, October 19, 2018

Create custom Toast with layout XML

This example show how to create custom Toast with layout XML, to include a ImageView, fixed text and custom message.


Create the layout XML, layout/layout_mytoast.xml.
<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    android:background="@android:drawable/screen_background_dark_transparent">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/ic_launcher_round"/>
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="left"
            android:textSize="14dp"
            android:textStyle="italic"
            android:text="MY TOAST"
            />
        <TextView
            android:id="@android:id/message"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:shadowColor="#BB000000"
            android:shadowRadius="5"
            android:textSize="16dp"
            android:textStyle="bold"
            />
    </LinearLayout>


</LinearLayout>


Java example:
package com.blogspot.android_er.mytoast2;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        showToast();
    }

    private void showToast(){
        /*
        Toast.makeText(MainActivity.this,
                "It's default Toast",
                Toast.LENGTH_LONG).show();
                */

        LayoutInflater inflater = getLayoutInflater();
        View toastView = inflater.inflate(R.layout.layout_mytoast, null);
        Toast myToast = new Toast(MainActivity.this);
        myToast.setView(toastView);
        myToast.setGravity
                (Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL,
                0, 0);
        myToast.setDuration(Toast.LENGTH_LONG);
        myToast.setText("It's my Toast with custom layout XML.");
        myToast.show();
    }
}




Related FYI:
The default layout of Toast should be located at:
...\android-sdk\platforms\<version>\data\res\layout\transient_notification.xml




How to capture screen in Android Studio

Follow the steps to capture screen of Android Emulator or connected Android device, using Android Studio. It work for me on Android Studio 3.2.1.

  1. Run your app on a connected device or emulator. If using a connected device, be sure you have enabled USB debugging.
  2. In Android Studio, select View > Tool Windows > Logcat to open Logcat.
  3. Select the device and a process from the drop-down at the top of the window.
  4. Click Screen Capture   on the left side of the window.

The screenshot appears in a Screenshot Editor window.


You can also rotate your captured screen or choose a device to wrap your screenshot with real device artwork; Drop Shadow, Screen Glare, or both.

source: https://developer.android.com/studio/debug/am-screenshot

Thursday, October 18, 2018

Make TRANSPARENT Toast

It's a simple way to make TRANSPARENT Toast.

Java
package com.blogspot.android_er.mycustomtoast;

import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        displayMyToast();
    }

    private void displayMyToast(){
        Toast myToast = Toast.makeText(MainActivity.this,
                "I'm a TRANSPARENT Toast",
                Toast.LENGTH_LONG);
        View view = myToast.getView();
        view.setBackgroundColor(Color.TRANSPARENT);
        myToast.show();
    }
}


Kotlin, generated in Android Studio by menu > Code > Convert Java file to Kotlin File.
package com.blogspot.android_er.mycustomtoast

import android.graphics.Color
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.widget.Toast

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        displayMyToast()
    }

    private fun displayMyToast() {
        val myToast = Toast.makeText(this@MainActivity,
                "I'm a TRANSPARENT Toast",
                Toast.LENGTH_LONG)
        val view = myToast.view
        view.setBackgroundColor(Color.TRANSPARENT)
        myToast.show()
    }
}




Next:
- Create custom Toast with layout XML

Wednesday, October 17, 2018

How to build for Android Pie (Go Edition)

This video, by Android Developers, describe how to build for Android Pie (Go Edition) and grow your app or game business.


Android (Go Edition) provides a fast and optimized mobile experience for over 200 devices in more than 120 countries. Android (Go Edition) is an opportunity for your apps to reach a global audience. Learn more about how to build for Android Pie (Go Edition) and grow your app or game business.

Building for Billions guidelines and best practices → http://bit.ly/2R1mz71
How to shrink your code and resources → http://bit.ly/2IijICV
Learn more about APK Analyzer → http://bit.ly/2Q9x6Me
Learn more about Android App Bundle → http://bit.ly/2OTqkKi
How to optimize your app for Android Go → http://bit.ly/2OdXU0t
How your app’s APK size impacts install conversion rates → http://bit.ly/2DwM2CF


What is Android Go?


Compare Stock Android vs Android One vs Android Go

Monday, October 15, 2018

Monitor memory related events with onTrimMemory(), and simulate memory low in Android Emulator using adb

Android can reclaim memory from your app or kill your app entirely if necessary to free up memory for critical tasks. To help balance the system memory and avoid the system's need to kill your app process, you can implement the ComponentCallbacks2 interface and override onTrimMemory() callback method to listen for memory related events when your app is in either the foreground or the background, and then release objects in response to app lifecycle or system events that indicate the system needs to reclaim memory. 

When the system begins killing processes in the LRU cache, it primarily works bottom-up. The system also considers which processes consume more memory and thus provide the system more memory gain if killed. The less memory you consume while in the LRU list overall, the better your chances are to remain in the list and be able to quickly resume.

Here is a example code to implement the ComponentCallbacks2 interface and override onTrimMemory() callback method.

package com.blogspot.android_er.androidontrimmemory;

import android.content.ComponentCallbacks2;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;

/*
http://android-er.blogspot.com/
Example to use onTrimMemory()
 */
public class MainActivity extends AppCompatActivity
        implements ComponentCallbacks2 {

    private static final String TAG = "MyActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Log.v(TAG, "onCreate() called");
    }

    public void onTrimMemory(int level){
        Log.v(TAG, "onTrimMemory(" + level + ")");
        switch(level){

            case ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN:
                Log.v(TAG, "TRIM_MEMORY_UI_HIDDEN");
                break;
            case ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE:
                Log.v(TAG, "TRIM_MEMORY_RUNNING_MODERATE");
                break;
            case ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW:
                Log.v(TAG, "TRIM_MEMORY_RUNNING_LOW");
                break;
            case ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL:
                Log.v(TAG, "TRIM_MEMORY_RUNNING_CRITICA");
                break;
            case ComponentCallbacks2.TRIM_MEMORY_BACKGROUND:
                Log.v(TAG, "TRIM_MEMORY_BACKGROUND");
                break;
            case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
                Log.v(TAG, "TRIM_MEMORY_MODERATE");
                break;
            case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
                Log.v(TAG, "TRIM_MEMORY_COMPLETE");
                break;

            default:
                Log.v(TAG, "default");
        }
    }

}


To simulate the memory low condition, you can use the adb command:

adb shell am send-trim-memory

Example for my case, it's:

adb shell am send-trim-memory com.blogspot.android_er.androidontrimmemory MODERATE

Notice that you cannot set background level if your app is in foreground. Otherwise the following exception will be thrown, as shown in the video.

java.lang.IllegalArgumentException: Unable to set a background trim level on a foreground process



reference:
Overview of memory management
Manage your app's memory





Friday, October 12, 2018

Android Studio tips: improve build by setting org.gradle.jvmargs in Gradle script

Dex In Process (introduced from Android 2.1) is a feature that can improve build times, as well as Instant Run performance. To take advantage of Dex In Process, you’ll need to modify your gradle.properties file and increase the amount of memory allocated to the Gradle Daemon VM to a minimum of 2 Gb, using the org.gradle.jvmargs property.

org.gradle.jvmargs=-Xmx2048m



reference:


Learn more here about how to enable Dex In Process: Faster Android Studio Builds with Dex In Process




Wednesday, October 10, 2018

Made by Google 2018

Find out what we've been up to this year. Pixel 3 XL phones, an update to Chromecast, new Android Watches and more...

#madebygoogle


Monday, October 8, 2018

Sunday, October 7, 2018

Free ebook - Machine Learning Algorithms

Free ebook by PacktPub - Machine Learning Algorithms


Build strong foundation for entering the world of machine learning and data science with the help of this comprehensive guide

  • Get started in the field of Machine Learning with the help of this solid, concept-rich, yet highly practical guide.
  • Your one-stop solution for everything that matters in mastering the whats and whys of Machine Learning algorithms and their implementation.
  • Get a solid foundation for your entry into Machine Learning by strengthening your roots (algorithms) with this comprehensive guide.