1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
17package com.example.android.leanback;
18
19import android.app.Activity;
20import android.graphics.Bitmap;
21import android.graphics.drawable.BitmapDrawable;
22import android.graphics.drawable.Drawable;
23import android.os.AsyncTask;
24import android.os.Handler;
25import android.support.v17.leanback.app.BackgroundManager;
26import android.support.v4.content.ContextCompat;
27import android.util.Log;
28
29public class BackgroundHelper {
30
31    private static final String TAG = "BackgroundHelper";
32    private static final boolean DEBUG = false;
33    private static final boolean ENABLED = true;
34
35    // Background delay serves to avoid kicking off expensive bitmap loading
36    // in case multiple backgrounds are set in quick succession.
37    private static final int SET_BACKGROUND_DELAY_MS = 100;
38
39    static class Request {
40        Object mImageToken;
41        Activity mActivity;
42        Bitmap mResult;
43
44        Request(Activity activity, Object imageToken) {
45            mActivity = activity;
46            mImageToken = imageToken;
47        }
48    }
49
50    public BackgroundHelper() {
51        if (DEBUG && !ENABLED) Log.v(TAG, "BackgroundHelper: disabled");
52    }
53
54    class LoadBackgroundRunnable implements Runnable {
55        Request mRequest;
56
57        LoadBackgroundRunnable(Activity activity, Object imageToken) {
58            mRequest = new Request(activity, imageToken);
59        }
60
61        @Override
62        public void run() {
63            if (mTask != null) {
64                if (DEBUG) Log.v(TAG, "Cancelling task");
65                mTask.cancel(true);
66            }
67            if (DEBUG) Log.v(TAG, "Executing task");
68            mTask = new LoadBitmapTask();
69            mTask.execute(mRequest);
70            mRunnable = null;
71        }
72    };
73
74    class LoadBitmapTask extends AsyncTask<Request, Object, Request> {
75        @Override
76        protected Request doInBackground(Request... params) {
77            boolean cancelled = isCancelled();
78            if (DEBUG) Log.v(TAG, "doInBackground cancelled " + cancelled);
79            Request request = params[0];
80            if (!cancelled) {
81                request.mResult = loadBitmap(request.mActivity, request.mImageToken);
82            }
83            return request;
84        }
85
86        @Override
87        protected void onPostExecute(Request request) {
88            if (DEBUG) Log.v(TAG, "onPostExecute");
89            applyBackground(request.mActivity, request.mResult);
90            if (mTask == this) {
91                mTask = null;
92            }
93        }
94
95        @Override
96        protected void onCancelled(Request request) {
97            if (DEBUG) Log.v(TAG, "onCancelled");
98        }
99
100        private Bitmap loadBitmap(Activity activity, Object imageToken) {
101            if (imageToken instanceof Integer) {
102                final int resourceId = (Integer) imageToken;
103                if (DEBUG) Log.v(TAG, "load resourceId " + resourceId);
104                Drawable drawable = ContextCompat.getDrawable(activity, resourceId);
105                if (drawable instanceof BitmapDrawable) {
106                    return ((BitmapDrawable) drawable).getBitmap();
107                }
108            }
109            return null;
110        }
111
112        private void applyBackground(Activity activity, Bitmap bitmap) {
113            BackgroundManager backgroundManager = BackgroundManager.getInstance(activity);
114            if (backgroundManager == null || !backgroundManager.isAttached()) {
115                return;
116            }
117            backgroundManager.setBitmap(bitmap);
118        }
119    }
120
121    private LoadBackgroundRunnable mRunnable;
122    private LoadBitmapTask mTask;
123
124    // Allocate a dedicated handler because there may be no view available
125    // when setBackground is invoked.
126    private Handler mHandler = new Handler();
127
128    public void setBackground(Activity activity, Object imageToken) {
129        if (!ENABLED) {
130            return;
131        }
132        if (mRunnable != null) {
133            mHandler.removeCallbacks(mRunnable);
134        }
135        mRunnable = new LoadBackgroundRunnable(activity, imageToken);
136        mHandler.postDelayed(mRunnable, SET_BACKGROUND_DELAY_MS);
137    }
138
139    static public void attach(Activity activity) {
140        if (!ENABLED) {
141            return;
142        }
143        if (DEBUG) Log.v(TAG, "attach to activity " + activity);
144        BackgroundManager.getInstance(activity).attach(activity.getWindow());
145    }
146
147    static public void release(Activity activity) {
148        if (!ENABLED) {
149            return;
150        }
151        if (DEBUG) Log.v(TAG, "release from activity " + activity);
152        BackgroundManager.getInstance(activity).release();
153    }
154}
155