com.google.android.apps.muzei.datalayer.ActivateMuzeiIntentService.java Source code

Java tutorial

Introduction

Here is the source code for com.google.android.apps.muzei.datalayer.ActivateMuzeiIntentService.java

Source

/*
 * Copyright 2014 Google Inc.
 *
 * Licensed 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.
 */

package com.google.android.apps.muzei.datalayer;

import android.app.IntentService;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.ResultReceiver;
import android.preference.PreferenceManager;
import android.service.notification.StatusBarNotification;
import android.support.v4.app.NotificationCompat;
import android.support.v4.content.ContextCompat;
import android.support.wearable.activity.ConfirmationActivity;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.wearable.CapabilityApi;
import com.google.android.gms.wearable.Node;
import com.google.android.gms.wearable.Wearable;
import com.google.android.wearable.intent.RemoteIntent;
import com.google.android.wearable.playstore.PlayStoreAvailability;
import com.google.firebase.analytics.FirebaseAnalytics;

import net.nurik.roman.muzei.R;

import java.io.IOException;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.TimeUnit;

public class ActivateMuzeiIntentService extends IntentService {
    private static final String TAG = "ActivateMuzeiService";
    private static final int INSTALL_NOTIFICATION_ID = 3113;
    private static final int ACTIVATE_NOTIFICATION_ID = 3114;
    private static final String ACTIVATE_MUZEI_NOTIF_SHOWN_PREF_KEY = "ACTIVATE_MUZEI_NOTIF_SHOWN";
    private static final String ACTION_MARK_NOTIFICATION_READ = "com.google.android.apps.muzei.action.NOTIFICATION_DELETED";
    private static final String ACTION_REMOTE_INSTALL_MUZEI = "com.google.android.apps.muzei.action.REMOTE_INSTALL_MUZEI";

    public static void maybeShowActivateMuzeiNotification(Context context) {
        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
        if (preferences.getBoolean(ACTIVATE_MUZEI_NOTIF_SHOWN_PREF_KEY, false)) {
            return;
        }
        NotificationManager notificationManager = (NotificationManager) context
                .getSystemService(NOTIFICATION_SERVICE);
        StatusBarNotification[] notifications = notificationManager.getActiveNotifications();
        boolean hasInstallNotification = false;
        boolean hasActivateNotification = false;
        for (StatusBarNotification notification : notifications) {
            if (notification.getId() == INSTALL_NOTIFICATION_ID) {
                hasInstallNotification = true;
            } else if (notification.getId() == ACTIVATE_NOTIFICATION_ID) {
                hasActivateNotification = true;
            }
        }
        NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
        builder.setSmallIcon(R.drawable.ic_stat_muzei)
                .setColor(ContextCompat.getColor(context, R.color.notification))
                .setPriority(NotificationCompat.PRIORITY_MAX).setDefaults(NotificationCompat.DEFAULT_VIBRATE)
                .setAutoCancel(true).setContentTitle(context.getString(R.string.activate_title));
        Intent deleteIntent = new Intent(context, ActivateMuzeiIntentService.class);
        deleteIntent.setAction(ACTION_MARK_NOTIFICATION_READ);
        builder.setDeleteIntent(PendingIntent.getService(context, 0, deleteIntent, 0));
        // Check if the Muzei main app is installed
        GoogleApiClient googleApiClient = new GoogleApiClient.Builder(context).addApi(Wearable.API).build();
        ConnectionResult connectionResult = googleApiClient.blockingConnect(30, TimeUnit.SECONDS);
        Set<Node> nodes = new TreeSet<>();
        if (connectionResult.isSuccess()) {
            nodes = Wearable.CapabilityApi
                    .getCapability(googleApiClient, "activate_muzei", CapabilityApi.FILTER_ALL).await()
                    .getCapability().getNodes();
            googleApiClient.disconnect();
        }
        if (nodes.isEmpty()) {
            if (hasInstallNotification) {
                // No need to repost the notification
                return;
            }
            // Send an install Muzei notification
            if (PlayStoreAvailability.getPlayStoreAvailabilityOnPhone(
                    context) != PlayStoreAvailability.PLAY_STORE_ON_PHONE_AVAILABLE) {
                builder.setContentText(context.getString(R.string.activate_no_play_store));
                FirebaseAnalytics.getInstance(context).logEvent("activate_notif_no_play_store", null);
            } else {
                builder.setContentText(context.getString(R.string.activate_install_muzei));
                Intent installMuzeiIntent = new Intent(context, ActivateMuzeiIntentService.class);
                installMuzeiIntent.setAction(ACTION_REMOTE_INSTALL_MUZEI);
                PendingIntent pendingIntent = PendingIntent.getService(context, 0, installMuzeiIntent, 0);
                builder.addAction(new NotificationCompat.Action.Builder(R.drawable.open_on_phone,
                        context.getString(R.string.activate_install_action), pendingIntent)
                                .extend(new NotificationCompat.Action.WearableExtender()
                                        .setHintDisplayActionInline(true).setAvailableOffline(false))
                                .build());
                builder.extend(new NotificationCompat.WearableExtender().setContentAction(0));
                FirebaseAnalytics.getInstance(context).logEvent("activate_notif_play_store", null);
            }
            notificationManager.notify(INSTALL_NOTIFICATION_ID, builder.build());
            return;
        }
        // else, Muzei is installed on the phone/tablet, but not activated
        if (hasInstallNotification) {
            // Clear any install Muzei notification
            notificationManager.cancel(INSTALL_NOTIFICATION_ID);
        }
        if (hasActivateNotification) {
            // No need to repost the notification
            return;
        }
        String nodeName = nodes.iterator().next().getDisplayName();
        builder.setContentText(context.getString(R.string.activate_enable_muzei, nodeName));
        Intent launchMuzeiIntent = new Intent(context, ActivateMuzeiIntentService.class);
        PendingIntent pendingIntent = PendingIntent.getService(context, 0, launchMuzeiIntent, 0);
        builder.addAction(new NotificationCompat.Action.Builder(R.drawable.open_on_phone,
                context.getString(R.string.activate_action, nodeName), pendingIntent)
                        .extend(new NotificationCompat.Action.WearableExtender().setHintDisplayActionInline(true)
                                .setAvailableOffline(false))
                        .build());
        Bitmap background = null;
        try {
            background = BitmapFactory.decodeStream(context.getAssets().open("starrynight.jpg"));
        } catch (IOException e) {
            Log.e(TAG, "Error reading default background asset", e);
        }
        builder.extend(new NotificationCompat.WearableExtender().setContentAction(0).setBackground(background));
        FirebaseAnalytics.getInstance(context).logEvent("activate_notif_installed", null);
        notificationManager.notify(ACTIVATE_NOTIFICATION_ID, builder.build());
    }

    public static void clearNotifications(Context context) {
        NotificationManager notificationManager = (NotificationManager) context
                .getSystemService(NOTIFICATION_SERVICE);
        notificationManager.cancel(INSTALL_NOTIFICATION_ID);
        notificationManager.cancel(ACTIVATE_NOTIFICATION_ID);
    }

    public ActivateMuzeiIntentService() {
        super(TAG);
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
        String action = intent.getAction();
        if (TextUtils.equals(action, ACTION_MARK_NOTIFICATION_READ)) {
            preferences.edit().putBoolean(ACTIVATE_MUZEI_NOTIF_SHOWN_PREF_KEY, true).apply();
            return;
        } else if (TextUtils.equals(action, ACTION_REMOTE_INSTALL_MUZEI)) {
            Intent remoteIntent = new Intent(Intent.ACTION_VIEW).addCategory(Intent.CATEGORY_BROWSABLE)
                    .setData(Uri.parse("market://details?id=" + getPackageName()));
            RemoteIntent.startRemoteActivity(this, remoteIntent, new ResultReceiver(new Handler()) {
                @Override
                protected void onReceiveResult(int resultCode, Bundle resultData) {
                    if (resultCode == RemoteIntent.RESULT_OK) {
                        FirebaseAnalytics.getInstance(ActivateMuzeiIntentService.this)
                                .logEvent("activate_notif_install_sent", null);
                        preferences.edit().putBoolean(ACTIVATE_MUZEI_NOTIF_SHOWN_PREF_KEY, true).apply();
                    } else {
                        Toast.makeText(ActivateMuzeiIntentService.this, R.string.activate_install_failed,
                                Toast.LENGTH_SHORT).show();
                    }
                }
            });
            return;
        }
        // else -> Open on Phone action
        GoogleApiClient googleApiClient = new GoogleApiClient.Builder(this).addApi(Wearable.API).build();
        ConnectionResult connectionResult = googleApiClient.blockingConnect(30, TimeUnit.SECONDS);
        if (!connectionResult.isSuccess()) {
            Log.e(TAG, "Failed to connect to GoogleApiClient.");
            Toast.makeText(this, R.string.activate_failed, Toast.LENGTH_SHORT).show();
            return;
        }
        Set<Node> nodes = Wearable.CapabilityApi
                .getCapability(googleApiClient, "activate_muzei", CapabilityApi.FILTER_REACHABLE).await()
                .getCapability().getNodes();
        if (nodes.isEmpty()) {
            Toast.makeText(this, R.string.activate_failed, Toast.LENGTH_SHORT).show();
        } else {
            FirebaseAnalytics.getInstance(this).logEvent("activate_notif_message_sent", null);
            // Show the open on phone animation
            Intent openOnPhoneIntent = new Intent(this, ConfirmationActivity.class);
            openOnPhoneIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            openOnPhoneIntent.putExtra(ConfirmationActivity.EXTRA_ANIMATION_TYPE,
                    ConfirmationActivity.OPEN_ON_PHONE_ANIMATION);
            startActivity(openOnPhoneIntent);
            // Clear the notification
            NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
            notificationManager.cancel(INSTALL_NOTIFICATION_ID);
            preferences.edit().putBoolean(ACTIVATE_MUZEI_NOTIF_SHOWN_PREF_KEY, true).apply();
            // Send the message to the phone to open Muzei
            for (Node node : nodes) {
                Wearable.MessageApi.sendMessage(googleApiClient, node.getId(), "notification/open", null).await();
            }
        }
        googleApiClient.disconnect();
    }
}