What's New on Android

Sidiq Permana

Google Developer Expert for Android

permana.sidiq@gmail.com

July - August 2015

Google Play Service 7.8.0

Official Android 6.0 SDK & FINAL M Preview

Android Studio 1.4 Preview 2 

Android Studio1.3.2

(Stable)

Android Experiments

Hot issue : Flatbuffers 

FlatBuffers is a serialization library for games and other memory constrained apps. Go to our landing page to browse our documentation.

FlatBuffers allows you to directly access serialized data without unpacking/parsing it first, while still having great forwards/backwards compatibility. FlatBuffers can be built for many different systems (Android, Windows, OS X, Linux)

Hmm... Pengganti JSON untuk yang lebih efficient ? silakan oprek lebih lanjut di sini 

Migrasi ke M ? Perhatikan app permissions 

Ada perubahan terhadap akses permissions yang ada di Android M dimana pengguna dapat mengizinkan atau tidak sebuah permission dapat berjalan atau tidak di aplikasi kita. Ini lebih pada permission yang berpengaruh sama privacy pengguna.

Normal Permission

Sejumlah permission yang tidak begitu 'mengusik' privacy pengguna yang tentunya tidak akan tampil pada app permission list. Contohnya : 

  • android.permission.ACCESS_LOCATION_EXTRA_COMMANDS
  • android.permission.ACCESS_NETWORK_STATE
  • android.permission.ACCESS_NOTIFICATION_POLICY
  • android.permission.ACCESS_WIFI_STATE
  • android.permission.ACCESS_WIMAX_STATE
  • android.permission.BLUETOOTH
  • android.permission.BLUETOOTH_ADMIN
  • android.permission.BROADCAST_STICKY
  • android.permission.CHANGE_NETWORK_STATE
  • android.permission.CHANGE_WIFI_MULTICAST_STATE
  • android.permission.CHANGE_WIFI_STATE
  • android.permission.CHANGE_WIMAX_STATE
  • android.permission.DISABLE_KEYGUARD
  • android.permission.EXPAND_STATUS_BAR
  • android.permission.FLASHLIGHT
  • android.permission.GET_ACCOUNTS
  • android.permission.GET_PACKAGE_SIZE
  • android.permission.INTERNET
  • android.permission.KILL_BACKGROUND_PROCESSES
  • android.permission.MODIFY_AUDIO_SETTINGS
  • android.permission.NFC
  • android.permission.READ_SYNC_SETTINGS
  • android.permission.READ_SYNC_STATS
  • android.permission.RECEIVE_BOOT_COMPLETED
  • android.permission.REORDER_TASKS
  • android.permission.REQUEST_INSTALL_PACKAGES
  • android.permission.SET_TIME_ZONE
  • android.permission.SET_WALLPAPER
  • android.permission.SET_WALLPAPER_HINTS
  • android.permission.SUBSCRIBED_FEEDS_READ
  • android.permission.TRANSMIT_IR
  • android.permission.USE_FINGERPRINT
  • android.permission.VIBRATE
  • android.permission.WAKE_LOCK
  • android.permission.WRITE_SYNC_SETTINGS
  • com.android.alarm.permission.SET_ALARM
  • com.android.launcher.permission.INSTALL_SHORTCUT
  • com.android.launcher.permission.UNINSTALL_SHORTCUT

'Privacy' Permissions

Ini yang akan tampil pada app permissions list yang ada dan tentunya aplikasi kita harus bisa handle semua kondisi untuk fungsi-fungsi yang menggunakan permission ini. Misal : Location, Access Contact, Access Gallery, Using Camera dsb. 

Doze Mode

  • Terjadi ketika device dalam keadaan tidak aktif atau off dalam periode waktu tertentu
  • Mode baru untuk menghemat batre
  • Semua background proses tidak bisa dijalankan kecuali GCM dengan prioritas
  • AlarmManager hanya diperbolehkan untuk setAndAllowWhileIdle()

App Standby

  • Aplikasi tidak digunakan dalam Jangka waktu yang lama
  • Tidak memiliki akses untuk melakukan proses di background dan terhubung ke network
  • Salah satu mekanisme baru untuk melakukan penghematan batre
  • Kembali aktif secara 'normal' jika pengguna menggunakannya kembali

Voice Interaction Api

Fitur Api baru yang memungkinkan aplikasi kita berinterasi dengan pengguna dengan menggunakan suara, ini menanamkan langsung fungsi Voice Interaction kedalam aplikasi kita dengan perantara Google. Api ini memanfaatkan fungsi Text-To-Speech dan Speech-To-Text yang sudah ada.

Voice Interaction Api Demo

Studi Kasus : Location Permission

build.gradle

apply plugin: 'com.android.application'

android {
    compileSdkVersion 'android-MNC'
    buildToolsVersion "21.1.2"

    defaultConfig {
        applicationId "com.sidiq.nbs.test.sampleapppermissions"
        minSdkVersion 15
        targetSdkVersion 22
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

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

PermissionUtil

public static boolean isMNC() {
        /*
         TODO: In the Android M Preview release, checking if the platform is M is done through
         the codename, not the version code. Once the API has been finalised, the following check
         should be used: */
        // return Build.VERSION.SDK_INT == Build.VERSION_CODES.MNC

        return "MNC".equals(Build.VERSION.CODENAME);
    }
public static boolean hasSelfPermission(Activity activity, String[] permissions) {
        // Below Android M all permissions are granted at install time and are already available.
        if (!isMNC()) {
            return true;
        }

        // Verify that all required permissions have been granted
        for (String permission : permissions) {
            if (activity.checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
                return false;
            }
        }
        return true;
    }

Implementasi

private static String[] PERMISSIONS_LOCATIONS = {Manifest.permission.ACCESS_COARSE_LOCATION,
            Manifest.permission.ACCESS_FINE_LOCATION};

Deklarasikan permission yang digunakan untuk spesifik fitur

Implementasi

if (PermissionUtil.isMNC()){
       accessLocation();
   }else{
       getUserLocation();
   }
private void accessLocation(){
        txtUserLocation.setText(getString(R.string.text_permission));
        if (PermissionUtil.hasSelfPermission(MainActivity.this, PERMISSIONS_LOCATIONS)){
            getUserLocation();
        }else{
            requestPermissions(PERMISSIONS_LOCATIONS, REQUEST_LOCATION);
        }
    }

Jika ya, maka lakukan validasi permission, belum tervalidasi maka kita request permission ke pengguna

Validasi apakah app kita berjalan di android M ?

Implementasi

@Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_LOCATION){
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED){
                getUserLocation();
            }else{
                txtUserLocation.setText(getString(R.string.text_nopermission));
            }
        }
    }

Callback method jika pengguna mengizinkan atau tidak

Hasil

Request permission hanya dilakukan sekali dan user bisa revoke permission melalui konfigurasi setting pada aplikasi 

Cara pengujian (1)

Rebuild project kamu dengan

compileSdkVersion = 'android-MNC' 

 atau 

compileSdkVersion = '23'

lalu build dan sync gradlenya. Make sure dengan Android Tools dan Platform-Tools yang baru

Cara Pengujian 2

Untuk aplikasi yang dibangun untuk api < MNC maka install aplikasinya dan kemudian revoke permission yang ada pada permission app dengan cara : settings --> Apps --> [Pilih App] --> Permissions. Jika sudah, coba jalankan kembali aplikasinya dan perhatikan perubahan perilaku yang ada. 

Apache HttpClient Removal

Tidak usah khawatir bagi kamu yang Apache HttpClient lover, cukup tambahkan ini di build.gradle(Module: app) maka semua akan baik-baik saja. 

android {
    useLibrary 'org.apache.http.legacy'
}

DataBinding

Berjalan lancar dengan Android Studio 1.3.1

Support sampai Api Level 7
Lib databinding untuk versi 1.3.0 sudah rilis

Update SDK Manager untuk : Android SDK Tools (23.3.4), Android SDK Platform-tools (23), Android Support Repository (17), Android Support Library (23)

Konfigurasi

 dependencies {
        classpath 'com.android.tools.build:gradle:1.3.+'
        classpath "com.android.databinding:dataBinder:1.+"
    }
apply plugin: 'com.android.application'
apply plugin: 'com.android.databinding'

android {
    compileSdkVersion 22
    buildToolsVersion "22.0.1"

    defaultConfig {
        applicationId "com.sidiq.nbs.test.simpledatabinding"
        minSdkVersion 15
        targetSdkVersion 22
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

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

Pada build.gradle(Project: yourProject)

Pada build.gradle(Module: app)

Layout

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable name="user" type="com.sidiq.nbs.test.simpledatabinding.User"/>
    </data>
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="16dp">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{user.firstName}"/>
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{user.lastName}"/>
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Replace"
            android:id="@+id/button"
            android:layout_gravity="left"
            android:onClick="onButtonClick"
            android:layout_marginTop="10dp"/>
    </LinearLayout>
</layout>

Model

public class User extends BaseObservable {
    String firstName, lastName;

    public User(String firstName, String lastName){
        this.firstName = firstName;
        this.lastName = lastName;
    }

    @Bindable
    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
        notifyPropertyChanged(com.sidiq.nbs.test.simpledatabinding.BR.firstName);
    }

    @Bindable
    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
        notifyPropertyChanged(com.sidiq.nbs.test.simpledatabinding.BR.lastName);
    }
}

Activity

public class MainActivity extends AppCompatActivity {
    private User user;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        getSupportActionBar().setTitle("Simple Data Binding");

        ActivityMainBinding binding = DataBindingUtil.setContentView(MainActivity.this, 
                R.layout.activity_main);
        user = new User("Sidiq", "Permana");
        binding.setUser(user);

    }

    public void onButtonClick(View view){
        user.setFirstName("Wayne");
        user.setLastName("Rooney");
    }
}

Referensi lebih lanjut

Terima Kasih