Back to project page Muzei.
The source code is released under:
Apache License
If you think the Android project Muzei listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
/* * Copyright 2014 Google Inc./*from ww w. j a v a2s.c o m*/ * * 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; import android.app.WallpaperManager; import android.os.Bundle; import android.os.Handler; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.ViewConfiguration; import com.google.android.apps.muzei.event.ArtDetailOpenedClosedEvent; import com.google.android.apps.muzei.event.LockScreenVisibleChangedEvent; import com.google.android.apps.muzei.event.WallpaperActiveStateChangedEvent; import com.google.android.apps.muzei.event.WallpaperSizeChangedEvent; import com.google.android.apps.muzei.render.MuzeiBlurRenderer; import com.google.android.apps.muzei.render.RealRenderController; import com.google.android.apps.muzei.render.RenderController; import net.rbgrn.android.glwallpaperservice.GLWallpaperService; import de.greenrobot.event.EventBus; public class MuzeiWallpaperService extends GLWallpaperService { private LockScreenVisibleReceiver mLockScreenVisibleReceiver; @Override public Engine onCreateEngine() { return new MuzeiWallpaperEngine(); } @Override public void onCreate() { super.onCreate(); mLockScreenVisibleReceiver = new LockScreenVisibleReceiver(); mLockScreenVisibleReceiver.setupRegisterDeregister(this); } @Override public void onDestroy() { super.onDestroy(); if (mLockScreenVisibleReceiver != null) { mLockScreenVisibleReceiver.destroy(); mLockScreenVisibleReceiver = null; } } private class MuzeiWallpaperEngine extends GLEngine implements RenderController.Callbacks, MuzeiBlurRenderer.Callbacks { private static final long TEMPORARY_FOCUS_DURATION_MILLIS = 3000; private Handler mMainThreadHandler = new Handler(); private RenderController mRenderController; private GestureDetector mGestureDetector; private MuzeiBlurRenderer mRenderer; private boolean mArtDetailMode = false; private boolean mVisible = true; private boolean mValidDoubleTap; @Override public void onCreate(SurfaceHolder surfaceHolder) { super.onCreate(surfaceHolder); mRenderer = new MuzeiBlurRenderer(MuzeiWallpaperService.this, this); mRenderer.setIsPreview(isPreview()); mRenderController = new RealRenderController(MuzeiWallpaperService.this, mRenderer, this); setEGLContextClientVersion(2); setEGLConfigChooser(8, 8, 8, 0, 0, 0); setRenderer(mRenderer); setRenderMode(RENDERMODE_WHEN_DIRTY); requestRender(); mGestureDetector = new GestureDetector(MuzeiWallpaperService.this, mGestureListener); if (!isPreview()) { EventBus.getDefault().postSticky(new WallpaperActiveStateChangedEvent(true)); } setTouchEventsEnabled(true); setOffsetNotificationsEnabled(true); EventBus.getDefault().registerSticky(this); } @Override public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) { super.onSurfaceChanged(holder, format, width, height); if (!isPreview()) { EventBus.getDefault().postSticky(new WallpaperSizeChangedEvent(width, height)); } mRenderController.reloadCurrentArtwork(true); } @Override public void onDestroy() { super.onDestroy(); EventBus.getDefault().unregister(this); if (!isPreview()) { EventBus.getDefault().postSticky(new WallpaperActiveStateChangedEvent(false)); } queueEvent(new Runnable() { @Override public void run() { if (mRenderer != null) { mRenderer.destroy(); } } }); mRenderController.destroy(); } public void onEventMainThread(final ArtDetailOpenedClosedEvent e) { if (e.isArtDetailOpened() == mArtDetailMode) { return; } mArtDetailMode = e.isArtDetailOpened(); cancelDelayedBlur(); queueEvent(new Runnable() { @Override public void run() { mRenderer.setIsBlurred(!e.isArtDetailOpened(), true); } }); } public void onEventMainThread(ArtDetailViewport e) { requestRender(); } public void onEventMainThread(LockScreenVisibleChangedEvent e) { final boolean blur = !e.isLockScreenVisible(); cancelDelayedBlur(); queueEvent(new Runnable() { @Override public void run() { mRenderer.setIsBlurred(blur, false); } }); } @Override public void onVisibilityChanged(boolean visible) { mVisible = visible; mRenderController.setVisible(visible); } @Override public void onOffsetsChanged(float xOffset, float yOffset, float xOffsetStep, float yOffsetStep, int xPixelOffset, int yPixelOffset) { super.onOffsetsChanged(xOffset, yOffset, xOffsetStep, yOffsetStep, xPixelOffset, yPixelOffset); mRenderer.setNormalOffsetX(xOffset); } @Override public Bundle onCommand(String action, int x, int y, int z, Bundle extras, boolean resultRequested) { // mValidDoubleTap previously set in the gesture listener if (WallpaperManager.COMMAND_TAP.equals(action) && mValidDoubleTap) { // Temporarily toggle focused/blurred queueEvent(new Runnable() { @Override public void run() { mRenderer.setIsBlurred(!mRenderer.isBlurred(), false); // Schedule a re-blur delayedBlur(); } }); // Reset the flag mValidDoubleTap = false; } return super.onCommand(action, x, y, z, extras, resultRequested); } @Override public void onTouchEvent(MotionEvent event) { super.onTouchEvent(event); mGestureDetector.onTouchEvent(event); // Delay blur from temporary refocus while touching the screen delayedBlur(); } private final Runnable mDoubleTapTimeout = new Runnable() { @Override public void run() { queueEvent(new Runnable() { @Override public void run() { mValidDoubleTap = false; } }); } }; private final GestureDetector.OnGestureListener mGestureListener = new GestureDetector.SimpleOnGestureListener() { @Override public boolean onDown(MotionEvent e) { return true; } @Override public boolean onDoubleTap(MotionEvent e) { if (mArtDetailMode) { // The main activity is visible, so discard any double touches since focus // should be forced on return true; } mValidDoubleTap = true; // processed in onCommand/COMMAND_TAP mMainThreadHandler.removeCallbacks(mDoubleTapTimeout); final int timeout = ViewConfiguration.getDoubleTapTimeout(); mMainThreadHandler.postDelayed(mDoubleTapTimeout, timeout); return true; } }; private void cancelDelayedBlur() { mMainThreadHandler.removeCallbacks(mBlurRunnable); } private void delayedBlur() { if (mArtDetailMode || mRenderer.isBlurred()) { return; } cancelDelayedBlur(); mMainThreadHandler.postDelayed(mBlurRunnable, TEMPORARY_FOCUS_DURATION_MILLIS); } private Runnable mBlurRunnable = new Runnable() { @Override public void run() { queueEvent(new Runnable() { @Override public void run() { mRenderer.setIsBlurred(true, false); } }); } }; @Override public void requestRender() { if (mVisible) { super.requestRender(); } } @Override public void queueEventOnGlThread(Runnable runnable) { queueEvent(runnable); } } }