1 /* 2 * Copyright (C) 2009 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 17 package com.android.wallpaper.livepicker; 18 19 import android.app.ActionBar; 20 import android.app.Activity; 21 import android.app.AlertDialog; 22 import android.app.WallpaperManager; 23 import android.app.WallpaperInfo; 24 import android.app.Dialog; 25 import android.content.DialogInterface; 26 import android.graphics.Rect; 27 import android.service.wallpaper.IWallpaperConnection; 28 import android.service.wallpaper.IWallpaperService; 29 import android.service.wallpaper.IWallpaperEngine; 30 import android.service.wallpaper.WallpaperSettingsActivity; 31 import android.content.ServiceConnection; 32 import android.content.Intent; 33 import android.content.Context; 34 import android.content.ComponentName; 35 import android.os.RemoteException; 36 import android.os.IBinder; 37 import android.os.ParcelFileDescriptor; 38 import android.os.Bundle; 39 import android.service.wallpaper.WallpaperService; 40 import android.view.Menu; 41 import android.view.MenuItem; 42 import android.view.MotionEvent; 43 import android.view.View; 44 import android.view.WindowManager; 45 import android.view.ViewGroup; 46 import android.view.Window; 47 import android.view.LayoutInflater; 48 import android.util.Log; 49 import android.widget.TextView; 50 51 import java.io.IOException; 52 53 public class LiveWallpaperPreview extends Activity { 54 static final String EXTRA_LIVE_WALLPAPER_INFO = "android.live_wallpaper.info"; 55 56 private static final String LOG_TAG = "LiveWallpaperPreview"; 57 58 private WallpaperManager mWallpaperManager; 59 private WallpaperConnection mWallpaperConnection; 60 61 private String mSettings; 62 private String mPackageName; 63 private Intent mWallpaperIntent; 64 65 private View mView; 66 private Dialog mDialog; 67 68 @Override onCreate(Bundle savedInstanceState)69 protected void onCreate(Bundle savedInstanceState) { 70 super.onCreate(savedInstanceState); 71 init(); 72 } 73 init()74 protected void init() { 75 Bundle extras = getIntent().getExtras(); 76 WallpaperInfo info = extras.getParcelable(EXTRA_LIVE_WALLPAPER_INFO); 77 if (info == null) { 78 setResult(RESULT_CANCELED); 79 finish(); 80 } 81 82 initUI(info); 83 } 84 initUI(WallpaperInfo info)85 protected void initUI(WallpaperInfo info) { 86 mSettings = info.getSettingsActivity(); 87 mPackageName = info.getPackageName(); 88 mWallpaperIntent = new Intent(WallpaperService.SERVICE_INTERFACE) 89 .setClassName(info.getPackageName(), info.getServiceName()); 90 91 final ActionBar actionBar = getActionBar(); 92 actionBar.setCustomView(R.layout.live_wallpaper_preview); 93 mView = actionBar.getCustomView(); 94 95 mWallpaperManager = WallpaperManager.getInstance(this); 96 mWallpaperConnection = new WallpaperConnection(mWallpaperIntent); 97 } 98 99 @Override onCreateOptionsMenu(Menu menu)100 public boolean onCreateOptionsMenu(Menu menu) { 101 if (mSettings != null) { 102 getMenuInflater().inflate(R.menu.menu_preview, menu); 103 } 104 return super.onCreateOptionsMenu(menu); 105 } 106 setLiveWallpaper(final View v)107 public void setLiveWallpaper(final View v) { 108 if (mWallpaperManager.getWallpaperId(WallpaperManager.FLAG_LOCK) < 0) { 109 // The lock screen does not have a wallpaper, so no need to prompt; can only set both. 110 try { 111 setLiveWallpaper(v.getRootView().getWindowToken()); 112 setResult(RESULT_OK); 113 } catch (RuntimeException e) { 114 Log.w(LOG_TAG, "Failure setting wallpaper", e); 115 } 116 finish(); 117 } else { 118 // Otherwise, prompt to either set on home or both home and lock screen. 119 new AlertDialog.Builder(this) 120 .setTitle(R.string.set_live_wallpaper) 121 .setItems(R.array.which_wallpaper_options, new DialogInterface.OnClickListener() { 122 @Override 123 public void onClick(DialogInterface dialog, int which) { 124 try { 125 setLiveWallpaper(v.getRootView().getWindowToken()); 126 if (which == 1) { 127 // "Home screen and lock screen"; clear the lock screen so it 128 // shows through to the live wallpaper on home. 129 mWallpaperManager.clear(WallpaperManager.FLAG_LOCK); 130 } 131 setResult(RESULT_OK); 132 } catch (RuntimeException e) { 133 Log.w(LOG_TAG, "Failure setting wallpaper", e); 134 } catch (IOException e) { 135 Log.w(LOG_TAG, "Failure setting wallpaper", e); 136 } 137 finish(); 138 } 139 }) 140 .show(); 141 } 142 } 143 setLiveWallpaper(IBinder windowToken)144 private void setLiveWallpaper(IBinder windowToken) { 145 mWallpaperManager.setWallpaperComponent(mWallpaperIntent.getComponent()); 146 mWallpaperManager.setWallpaperOffsetSteps(0.5f, 0.0f); 147 mWallpaperManager.setWallpaperOffsets(windowToken, 0.5f, 0.0f); 148 } 149 150 @Override onOptionsItemSelected(MenuItem item)151 public boolean onOptionsItemSelected(MenuItem item) { 152 if (item.getItemId() == R.id.configure) { 153 Intent intent = new Intent(); 154 intent.setComponent(new ComponentName(mPackageName, mSettings)); 155 intent.putExtra(WallpaperSettingsActivity.EXTRA_PREVIEW_MODE, true); 156 startActivity(intent); 157 return true; 158 } 159 return super.onOptionsItemSelected(item); 160 } 161 162 @Override onResume()163 public void onResume() { 164 super.onResume(); 165 if (mWallpaperConnection != null && mWallpaperConnection.mEngine != null) { 166 try { 167 mWallpaperConnection.mEngine.setVisibility(true); 168 } catch (RemoteException e) { 169 // Ignore 170 } 171 } 172 } 173 174 @Override onPause()175 public void onPause() { 176 super.onPause(); 177 if (mWallpaperConnection != null && mWallpaperConnection.mEngine != null) { 178 try { 179 mWallpaperConnection.mEngine.setVisibility(false); 180 } catch (RemoteException e) { 181 // Ignore 182 } 183 } 184 } 185 186 @Override onAttachedToWindow()187 public void onAttachedToWindow() { 188 super.onAttachedToWindow(); 189 190 showLoading(); 191 192 mView.post(new Runnable() { 193 public void run() { 194 if (!mWallpaperConnection.connect()) { 195 mWallpaperConnection = null; 196 } 197 } 198 }); 199 } 200 showLoading()201 private void showLoading() { 202 LayoutInflater inflater = LayoutInflater.from(this); 203 TextView content = (TextView) inflater.inflate(R.layout.live_wallpaper_loading, null); 204 205 mDialog = new Dialog(this, android.R.style.Theme_Black); 206 207 Window window = mDialog.getWindow(); 208 WindowManager.LayoutParams lp = window.getAttributes(); 209 210 lp.width = WindowManager.LayoutParams.MATCH_PARENT; 211 lp.height = WindowManager.LayoutParams.MATCH_PARENT; 212 window.setType(WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA); 213 214 mDialog.setContentView(content, new ViewGroup.LayoutParams( 215 ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT 216 )); 217 mDialog.show(); 218 } 219 220 @Override onDetachedFromWindow()221 public void onDetachedFromWindow() { 222 super.onDetachedFromWindow(); 223 224 if (mDialog != null) mDialog.dismiss(); 225 226 if (mWallpaperConnection != null) { 227 mWallpaperConnection.disconnect(); 228 } 229 mWallpaperConnection = null; 230 } 231 232 @Override dispatchTouchEvent(MotionEvent ev)233 public boolean dispatchTouchEvent(MotionEvent ev) { 234 if (mWallpaperConnection != null && mWallpaperConnection.mEngine != null) { 235 MotionEvent dup = MotionEvent.obtainNoHistory(ev); 236 try { 237 mWallpaperConnection.mEngine.dispatchPointer(dup); 238 } catch (RemoteException e) { 239 } 240 } 241 242 if (ev.getAction() == MotionEvent.ACTION_DOWN) { 243 onUserInteraction(); 244 } 245 boolean handled = getWindow().superDispatchTouchEvent(ev); 246 if (!handled) { 247 handled = onTouchEvent(ev); 248 } 249 250 if (!handled && mWallpaperConnection != null && mWallpaperConnection.mEngine != null) { 251 int action = ev.getActionMasked(); 252 try { 253 if (action == MotionEvent.ACTION_UP) { 254 mWallpaperConnection.mEngine.dispatchWallpaperCommand( 255 WallpaperManager.COMMAND_TAP, 256 (int) ev.getX(), (int) ev.getY(), 0, null); 257 } else if (action == MotionEvent.ACTION_POINTER_UP) { 258 int pointerIndex = ev.getActionIndex(); 259 mWallpaperConnection.mEngine.dispatchWallpaperCommand( 260 WallpaperManager.COMMAND_SECONDARY_TAP, 261 (int) ev.getX(pointerIndex), (int) ev.getY(pointerIndex), 0, null); 262 } 263 } catch (RemoteException e) { 264 } 265 } 266 return handled; 267 } 268 269 class WallpaperConnection extends IWallpaperConnection.Stub implements ServiceConnection { 270 final Intent mIntent; 271 IWallpaperService mService; 272 IWallpaperEngine mEngine; 273 boolean mConnected; 274 WallpaperConnection(Intent intent)275 WallpaperConnection(Intent intent) { 276 mIntent = intent; 277 } 278 connect()279 public boolean connect() { 280 synchronized (this) { 281 if (!bindService(mIntent, this, Context.BIND_AUTO_CREATE)) { 282 return false; 283 } 284 285 mConnected = true; 286 return true; 287 } 288 } 289 disconnect()290 public void disconnect() { 291 synchronized (this) { 292 mConnected = false; 293 if (mEngine != null) { 294 try { 295 mEngine.destroy(); 296 } catch (RemoteException e) { 297 // Ignore 298 } 299 mEngine = null; 300 } 301 unbindService(this); 302 mService = null; 303 } 304 } 305 onServiceConnected(ComponentName name, IBinder service)306 public void onServiceConnected(ComponentName name, IBinder service) { 307 if (mWallpaperConnection == this) { 308 mService = IWallpaperService.Stub.asInterface(service); 309 try { 310 final View view = mView; 311 final View root = view.getRootView(); 312 mService.attach(this, view.getWindowToken(), 313 WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY, 314 true, root.getWidth(), root.getHeight(), 315 new Rect(0, 0, 0, 0)); 316 } catch (RemoteException e) { 317 Log.w(LOG_TAG, "Failed attaching wallpaper; clearing", e); 318 } 319 } 320 } 321 onServiceDisconnected(ComponentName name)322 public void onServiceDisconnected(ComponentName name) { 323 mService = null; 324 mEngine = null; 325 if (mWallpaperConnection == this) { 326 Log.w(LOG_TAG, "Wallpaper service gone: " + name); 327 } 328 } 329 attachEngine(IWallpaperEngine engine)330 public void attachEngine(IWallpaperEngine engine) { 331 synchronized (this) { 332 if (mConnected) { 333 mEngine = engine; 334 try { 335 engine.setVisibility(true); 336 } catch (RemoteException e) { 337 // Ignore 338 } 339 } else { 340 try { 341 engine.destroy(); 342 } catch (RemoteException e) { 343 // Ignore 344 } 345 } 346 } 347 } 348 setWallpaper(String name)349 public ParcelFileDescriptor setWallpaper(String name) { 350 return null; 351 } 352 353 @Override engineShown(IWallpaperEngine engine)354 public void engineShown(IWallpaperEngine engine) throws RemoteException { 355 } 356 } 357 } 358