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