Android Nougat Quick Settings Tile

Filed Under: Android

In this tutorial, we’ll learn how to implement our own custom tiles in the quick settings.
This has been possible since Android Nougat. In our android application below, we’ll be creating a counter system which would keep a count of how many times you have opened the quick settings. It will display this in the Quick Setting Tile that we will implement.

Quick Settings Tile

The Android System provides a set of predefined tiles which are switches to easily access certain features in our smartphone. With an easy access to these switches, we can toggle features such as wifi, Bluetooth, mobile data, GPS etc.

Following is how it looks like:

android quick setting tiles

Clicking the sort button would show you the list of all tiles. You can drag the tiles into the top 10 visible tiles that would be shown in the notification tray.

The Quick Settings Tile is a new API that was released with Android Nougat.
A Tile has the following three states majorly:

  • STATE_ACTIVE
  • STATE_INACTIVE
  • STATE_UNAVAILABLE – the click action is disabled on the tile in this case

To create a tile in our android application we need to create a Service which extends TileService.
A TileService is a bound service. Hence it is tied to the Android System.

You need to add the TileService with the permissions in the AndroidManifest.xml file.


<service
  android:name=".MyTileService"
  android:icon="@drawable/ic_tile_default"
  android:label="@string/tile_name"
  android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
  <intent-filter>
    <action
      android:name="android.service.quicksettings.action.QS_TILE"/>
  </intent-filter>
</service>

The TileService has four important methods:

  • onClick() – When the tile is clicked.
  • onStartListening() – When you open the notification tray
  • onStopListening() – When you close the notification tray.
  • onTileAdded() – When the tile is added into the Quick tiles. This happens when the application is installed for the first time. This is the place where you set the settings on the tile in its initial state.
  • onTileRemoved() – When the tile is removed from the Quick Tiles.

We must set the UI of the tile. A Tile has three important components:

  • text
  • icon
  • state

After these have been set, you must call updateTile() on the Tile instance to update the UI in the Quick Settings.

We can launch activities by creating the intent method in the onClick() method of the TileService class.
startActivity just starts the activity but doesn’t close the notification tray holding the Quick Settings.
In order to close the tray, call startActivityAndCollapse method. It collapses the notification tray.

In the following section, we’ll be creating an android application which increments a counter variable each time you open the Quick Settings. It shows the count of the number of times you have opened the quick settings. A good way to keep a track of your productivity and how much many times you are opening the quick settings. We’ll store the count in SharedPreferences.

android quick setting tile project

Code

Update your AndroidManifest.xml with the following code:


<activity
            android:name=".MainActivity"
            android:launchMode="singleInstance">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service
            android:name=".MyTileService"
            android:icon="@android:drawable/ic_media_pause"
            android:label="Disabled"
            android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">

            <intent-filter>
                <action android:name="android.service.quicksettings.action.QS_TILE" />
            </intent-filter>
        </service>

Inside the Service above, we’ve set the icon and label for the Tile.
Inside the activity tag, we’ve set it to the single instance. This prevents creating multiple instances of the activity everytime startActivity is triggered.

The code for the MyTileService.java class is given below:


package com.journaldev.androidquicksettingstitle;


import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.drawable.Icon;
import android.preference.PreferenceManager;
import android.service.quicksettings.Tile;
import android.service.quicksettings.TileService;
import android.util.Log;
import android.widget.Toast;

public class MyTileService extends TileService {


    SharedPreferences mSharedPreferences;

    @Override
    public void onClick() {
        super.onClick();

         Tile tile = getQsTile();

        boolean isActive = (tile.getState() == Tile.STATE_ACTIVE);
        if (isActive) {
            tile.setState(Tile.STATE_INACTIVE);
            startActivityAndCollapse(new Intent(this, MainActivity.class));
            tile.setLabel("Disabled");
            tile.setContentDescription("Test App");
            tile.setIcon(Icon.createWithResource(this, android.R.drawable.ic_media_play));
        } else {
            mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
            int counter = mSharedPreferences.getInt("counter", 0);
            tile.setState(Tile.STATE_ACTIVE);
            tile.setIcon(Icon.createWithResource(this, android.R.drawable.ic_media_pause));
            tile.setLabel("Count " + counter);
        }
        tile.updateTile();
    }

    @Override
    public void onTileAdded() {
        super.onTileAdded();


        Tile tile = getQsTile();
        tile.setState(Tile.STATE_ACTIVE);


        mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
        int counter = mSharedPreferences.getInt("counter", 0);

        tile.setLabel("Count " + counter);

        tile.setIcon(Icon.createWithResource(this, android.R.drawable.ic_media_pause));
        tile.updateTile();

        Toast.makeText(getApplicationContext(), "tile added", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onTileRemoved() {
        super.onTileRemoved();
    }

    @Override
    public void onStartListening() {
        super.onStartListening();

        Tile tile = getQsTile();

        if (tile.getState() == Tile.STATE_ACTIVE) {
            mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
            int counter = mSharedPreferences.getInt("counter", 0);

            mSharedPreferences.edit().putInt("counter", ++counter).apply();
            tile.setLabel("Count " + counter);
        }

        tile.updateTile();

    }


    @Override
    public void onStopListening() {
        super.onStopListening();
    }


}

Inside onStartListening we check if the state is active or not. If it is, we update the counter and save it shared preferences.

Inside the onClick() we start the activity and dismiss the Quick Settings notification tray.

Tile tile = getQsTile(); is used to retrieve the Tile instance.

The code for the activity_main.xml layout is given below:


<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

The code for the MainActivity.java class is given below:


package com.journaldev.androidquicksettingstitle;

import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    TextView textView;
    SharedPreferences sharedPreferences;

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

        textView = findViewById(R.id.textView);
        sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);


        sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);

        int counter = sharedPreferences.getInt("counter", 0);
        textView.setText("You have opened the quick settings " + counter + " times.");
    }

    @Override
    protected void onResume() {
        super.onResume();

        sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);

        int counter = sharedPreferences.getInt("counter", 0);
        textView.setText("You have opened the quick settings " + counter + " times.");
    }


}

Inside the onResume() we update the TextView with the latest counter value from SharedPreferences.
onNewIntent() gets called everytime startActivity is executed with the Activity already running.

The output of the application in action is given below:

android quick tile output

This brings an end to this tutorial. You can download the project from the link below.

Leave a Reply

Your email address will not be published. Required fields are marked *

close
Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages