1 public class MainActivity extends Activity { 2 @Override 3 protected void onCreate(Bundle savedInstanceState) { 4 super.onCreate(savedInstanceState); 5 setContentView(R.layout.activity_main); 6 } 7 /** 开启小火箭 */ 8 public void start(View view) { 9 startService(new Intent(this, RocketService.class)); 10 finish(); 11 } 12 /** 取消小火箭 */ 13 public void cancel(View view) { 14 stopService(new Intent(this, RocketService.class)); 15 } 16 17 }
1 import android.content.Context; 2 import android.content.res.Resources; 3 import android.util.DisplayMetrics; 4 5 //工具类 6 public class DenstyUtil { 7 8 /** 9 * This method converts dp unit to equivalent pixels, depending on device 10 * density. 11 * 12 * @param dp 13 * A value in dp (density independent pixels) unit. Which we need 14 * to convert into pixels 15 * @param context 16 * Context to get resources and device specific display metrics 17 * @return A float value to represent px equivalent to dp depending on 18 * device density 19 */ 20 public static float convertDpToPixel(float dp, Context context) { 21 Resources resources = context.getResources(); 22 DisplayMetrics metrics = resources.getDisplayMetrics(); 23 float px = dp * (metrics.densityDpi / 160f); 24 return px; 25 } 26 27 /** 28 * This method converts device specific pixels to density independent 29 * pixels. 30 * 31 * @param px 32 * A value in px (pixels) unit. Which we need to convert into db 33 * @param context 34 * Context to get resources and device specific display metrics 35 * @return A float value to represent dp equivalent to px value 36 */ 37 public static float convertPixelsToDp(float px, Context context) { 38 Resources resources = context.getResources(); 39 DisplayMetrics metrics = resources.getDisplayMetrics(); 40 float dp = px / (metrics.densityDpi / 160f); 41 return dp; 42 } 43 44 }
1 import java.util.List; 2 import android.app.ActivityManager; 3 import android.app.ActivityManager.RunningServiceInfo; 4 import android.content.Context; 5 6 // 工具类 7 public class ServiceUtil { 8 9 /** 10 * 判断当前该服务是否在运行 11 * 12 * @param context 13 * @param cls 14 * @return 15 */ 16 public static boolean isServiceRunning(Context context, Class<?> cls) { 17 ActivityManager activityManager = (ActivityManager) context 18 .getSystemService(Context.ACTIVITY_SERVICE); 19 List<RunningServiceInfo> runningServices = activityManager 20 .getRunningServices(1024); 21 for (RunningServiceInfo service : runningServices) { 22 if (cls.getName().equals(service.service.getClassName())) { 23 return true; 24 } 25 } 26 return false; 27 } 28 }
1 import java.util.ArrayList; 2 import java.util.List; 3 import java.util.Timer; 4 import java.util.TimerTask; 5 import android.app.ActivityManager; 6 import android.app.ActivityManager.RunningTaskInfo; 7 import android.app.Service; 8 import android.content.Context; 9 import android.content.Intent; 10 import android.content.pm.PackageManager; 11 import android.content.pm.ResolveInfo; 12 import android.graphics.PixelFormat; 13 import android.graphics.drawable.AnimationDrawable; 14 import android.os.Handler; 15 import android.os.IBinder; 16 import android.os.Vibrator; 17 import android.util.DisplayMetrics; 18 import android.util.Log; 19 import android.view.Gravity; 20 import android.view.MotionEvent; 21 import android.view.View; 22 import android.view.View.OnTouchListener; 23 import android.view.WindowManager; 24 import android.view.WindowManager.LayoutParams; 25 import android.widget.ImageView; 26 import com.charon.rocketfly.R; 27 import com.charon.rocketfly.RocketActivity; 28 import com.charon.rocketfly.util.DenstyUtil; 29 30 public class RocketService extends Service { 31 protected static final String TAG = "RocketService"; 32 private WindowManager mWindowManager; 33 private int mWindowWidth; 34 private int mWindowHeight; 35 private static View icon; 36 private static View rocket_launcher; 37 38 private static AnimationDrawable mFireAnimationDrawable; 39 private static AnimationDrawable mLauncherAnimationDrawable; 40 41 private WindowManager.LayoutParams iconParams; 42 private WindowManager.LayoutParams launcherParams; 43 44 private static int mLauncherHeight; 45 private static int mLauncherWidth; 46 47 private Vibrator mVibrator; // 震动 48 49 private Timer timer; 50 51 private Handler mHandler = new Handler(); 52 53 @Override 54 public IBinder onBind(Intent intent) { 55 return null; 56 } 57 58 @Override 59 public void onCreate() { 60 super.onCreate(); 61 // 62 mWindowManager = (WindowManager) this.getApplicationContext() 63 .getSystemService(Context.WINDOW_SERVICE); 64 // 获取手机屏幕的分辨率和密度 (Pixels:像素) 65 DisplayMetrics displayMetrics = new DisplayMetrics(); 66 mWindowManager.getDefaultDisplay().getMetrics(displayMetrics); 67 mWindowWidth = displayMetrics.widthPixels; 68 mWindowHeight = displayMetrics.heightPixels; 69 70 // 取得震动服务的句柄 71 mVibrator = (Vibrator) this.getApplicationContext().getSystemService( 72 Context.VIBRATOR_SERVICE); 73 } 74 75 @Override 76 public int onStartCommand(Intent intent, int flags, int startId) { 77 Log.e(TAG, "on start command create icon"); 78 createIcon(); 79 if (timer == null) { 80 timer = new Timer(); 81 timer.scheduleAtFixedRate(new RefreshTask(), 0, 500); 82 } 83 return super.onStartCommand(intent, flags, startId); 84 } 85 86 @Override 87 public void onDestroy() { 88 removeIcon(); 89 removeLauncher(); 90 timer.cancel(); 91 timer = null; 92 super.onDestroy(); 93 } 94 95 /** 96 * 创建桌面悬浮窗,一旦点击就变成小火箭 97 */ 98 public void createIcon() { 99 removeIcon(); 100 iconParams = new LayoutParams(); 101 icon = new ImageView(this.getApplicationContext()); 102 Log.e(TAG, "creat icon is not null"); 103 icon.setBackgroundResource(R.drawable.floating_desktop_tips_rocket_bg); 104 105 icon.setOnTouchListener(new OnTouchListener() { 106 float startX = 0; 107 float startY = 0; 108 109 @Override 110 public boolean onTouch(View v, MotionEvent event) { 111 switch (event.getAction()) { 112 case MotionEvent.ACTION_DOWN: 113 // 手指一旦点击了后,就要去创建小火箭,和下面的发射台,并且给小火箭播放动画 114 startX = event.getX(); 115 startY = event.getY(); 116 117 // 小火箭升空图片 118 icon.setBackgroundResource(R.drawable.rocket_fire); 119 120 mFireAnimationDrawable = (AnimationDrawable) icon 121 .getBackground(); 122 mFireAnimationDrawable.start(); 123 iconParams.width = WindowManager.LayoutParams.WRAP_CONTENT; 124 iconParams.height = WindowManager.LayoutParams.WRAP_CONTENT; 125 iconParams.y = iconParams.y - iconParams.height 126 - icon.getHeight() * 2; 127 128 mWindowManager.updateViewLayout(icon, iconParams); 129 130 createLauncher(); 131 132 break; 133 case MotionEvent.ACTION_MOVE: 134 135 Log.d(TAG, "action move change the location"); 136 float newX = event.getRawX(); 137 Log.e(TAG, "iconHeight:" + icon.getHeight() + ":::" 138 + iconParams.height); 139 float newY = event.getRawY() - icon.getHeight() 140 - iconParams.height; 141 mWindowManager.updateViewLayout(icon, iconParams); 142 143 iconParams.x = (int) (newX - startX); 144 iconParams.y = (int) (newY - startY); 145 146 // 小火箭去移动位置 147 isReadyToLaunch(event.getRawX(), event.getRawY()); 148 149 break; 150 151 case MotionEvent.ACTION_UP: 152 // 手指抬起的时候,要么小火箭去发射,要么就是恢复到原来的提示图标那样 153 Log.d(TAG, "action up"); 154 if (isReadyToLaunch((int) event.getRawX(), 155 (int) event.getRawY())) { 156 Intent intent = new Intent(RocketService.this, 157 RocketActivity.class); 158 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 159 startActivity(intent); 160 removeIcon(); 161 removeLauncher(); 162 } else { 163 Log.e(TAG, "action up create icon."); 164 createIcon(); 165 icon.setBackgroundResource(R.drawable.floating_desktop_tips_rocket_bg); 166 } 167 168 break; 169 } 170 171 return true; 172 } 173 }); 174 175 iconParams.gravity = Gravity.LEFT | Gravity.TOP; 176 iconParams.x = mWindowWidth; 177 iconParams.y = mWindowHeight / 2; 178 iconParams.height = WindowManager.LayoutParams.WRAP_CONTENT; 179 iconParams.width = WindowManager.LayoutParams.WRAP_CONTENT; 180 iconParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE 181 | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; 182 iconParams.format = PixelFormat.TRANSLUCENT; 183 iconParams.type = WindowManager.LayoutParams.TYPE_PRIORITY_PHONE; 184 185 mWindowManager.addView(icon, iconParams); 186 } 187 188 private void removeIcon() { 189 if (icon != null && icon.getParent() != null) { 190 mWindowManager.removeView(icon); 191 icon = null; 192 } 193 removeLauncher(); 194 } 195 196 /** 197 * 创建桌面发射台 198 */ 199 private void createLauncher() { 200 removeLauncher(); 201 202 launcherParams = new LayoutParams(); 203 rocket_launcher = new ImageView(this.getApplicationContext()); 204 changelauncherState(false); 205 206 launcherParams.height = (int) DenstyUtil.convertDpToPixel(80, 207 this.getApplicationContext()); 208 launcherParams.width = (int) DenstyUtil.convertDpToPixel(200, 209 this.getApplicationContext()); 210 mLauncherHeight = launcherParams.height; 211 mLauncherWidth = launcherParams.width; 212 213 // 这个x、y是起始添加的位置 214 launcherParams.x = mWindowWidth / 2 - mLauncherWidth / 2; 215 launcherParams.y = mWindowHeight - mLauncherHeight; 216 launcherParams.gravity = Gravity.LEFT | Gravity.TOP; 217 218 Log.d(TAG, "create launcher. :" + rocket_launcher.getWidth()); 219 launcherParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE 220 | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; 221 launcherParams.format = PixelFormat.TRANSLUCENT; 222 launcherParams.type = WindowManager.LayoutParams.TYPE_TOAST; 223 224 mWindowManager.addView(rocket_launcher, launcherParams); 225 } 226 227 private void removeLauncher() { 228 if (rocket_launcher != null && rocket_launcher.getParent() != null) { 229 mWindowManager.removeView(rocket_launcher); 230 } 231 } 232 233 /** 234 * 更改发射台的状态 235 * 236 * @param isReadFly 237 * 是否可以进入发射状态 238 */ 239 private void changelauncherState(boolean isReadFly) { 240 if (rocket_launcher == null) { 241 return; 242 } 243 244 if (isReadFly) { 245 rocket_launcher.setBackgroundResource(R.drawable.desktop_bg_tips_3); 246 if (mLauncherAnimationDrawable != null) { 247 mLauncherAnimationDrawable.stop(); 248 } 249 } else { 250 rocket_launcher.setBackgroundResource(R.drawable.status_tip); 251 252 // 创建发射台 253 mLauncherAnimationDrawable = (AnimationDrawable) rocket_launcher 254 .getBackground(); 255 if (!mLauncherAnimationDrawable.isRunning()) { 256 mLauncherAnimationDrawable.start(); 257 } 258 } 259 } 260 261 /** 262 * 判断是否可以进行发射 263 * 264 * @param x 265 * 当前火箭的距x轴的距离 266 * @param y 267 * 当前火箭的距y轴的距离 268 * @return true为进入发射状态,反之为false 269 */ 270 private boolean isReadyToLaunch(float x, float y) { 271 if ((x > launcherParams.x && x < launcherParams.x 272 + launcherParams.width) 273 && (y > launcherParams.y)) { 274 changelauncherState(true); 275 Log.d(TAG, "is ready to launch.. true"); 276 mVibrator.vibrate(100); 277 return true; 278 } 279 changelauncherState(false); 280 return false; 281 } 282 283 /** 284 * 判断当前界面是否是桌面 285 * getRunningTasks(1):返回的个数。当前 运行的那个task。 286 * get(0):从task中获取到最顶层的activity,这个activity就是当前显示给用户的那个activity了 287 */ 288 private boolean isHome() { 289 ActivityManager mActivityManager = (ActivityManager) getSystemService( 290 Context.ACTIVITY_SERVICE); 291 List<RunningTaskInfo> rti = mActivityManager.getRunningTasks(1); 292 return getHomes().contains(rti.get(0).topActivity.getPackageName()); 293 } 294 295 /** 296 * 获得属于桌面的应用的应用包名称 297 * 298 * @return 返回包含所有包名的字符串列表 299 */ 300 private List<String> getHomes() { 301 List<String> names = new ArrayList<String>(); 302 PackageManager packageManager = this.getPackageManager(); 303 Intent intent = new Intent(Intent.ACTION_MAIN); 304 intent.addCategory(Intent.CATEGORY_HOME); 305 // 通过查询,获得所有ResolveInfo对象 306 List<ResolveInfo> resolveInfo = packageManager.queryIntentActivities( 307 intent, PackageManager.MATCH_DEFAULT_ONLY); 308 for (ResolveInfo ri : resolveInfo) { 309 names.add(ri.activityInfo.packageName); 310 } 311 return names; 312 } 313 314 private class RefreshTask extends TimerTask { 315 316 @Override 317 public void run() { 318 // 当前界面是桌面,且没有悬浮窗显示,则创建悬浮窗。 319 if (isHome()) { 320 mHandler.post(new Runnable() { 321 @Override 322 public void run() { 323 if (icon == null) { 324 Log.e(TAG, 325 "refresh task create icon, and the icon is null"); 326 createIcon(); 327 } 328 } 329 }); 330 331 } 332 // 当前界面不是桌面,且有悬浮窗显示,则移除悬浮窗。 333 else if (!isHome()) { 334 mHandler.post(new Runnable() { 335 @Override 336 public void run() { 337 removeIcon(); 338 } 339 }); 340 } 341 } 342 343 } 344 345 }
1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 android:layout_width="match_parent" 3 android:layout_height="match_parent" 4 android:background="@android:color/transparent" > 5 6 <ImageView 7 android:id="@+id/iv_rocket" 8 android:layout_width="wrap_content" 9 android:layout_height="wrap_content" 10 android:layout_alignParentBottom="true" 11 android:layout_centerHorizontal="true" 12 android:src="@drawable/rocket_fire" /> 13 14 <RelativeLayout 15 android:id="@+id/rl_cloud" 16 android:layout_width="wrap_content" 17 android:layout_height="wrap_content" > 18 19 <ImageView 20 android:id="@+id/iv_cloud" 21 android:layout_width="match_parent" 22 android:layout_height="wrap_content" 23 android:layout_alignParentBottom="true" 24 android:background="@drawable/desktop_smoke_m" 25 android:visibility="gone" /> 26 27 <ImageView 28 android:id="@+id/iv_cloud_line" 29 android:layout_width="wrap_content" 30 android:layout_height="wrap_content" 31 android:layout_above="@id/iv_cloud" 32 android:layout_centerHorizontal="true" 33 android:background="@drawable/desktop_smoke_t" 34 android:visibility="gone" /> 35 </RelativeLayout> 36 37 </RelativeLayout>
1 import android.app.Activity; 2 import android.content.Intent; 3 import android.graphics.drawable.AnimationDrawable; 4 import android.media.MediaPlayer; 5 import android.os.Bundle; 6 import android.util.Log; 7 import android.view.View; 8 import android.view.animation.AccelerateDecelerateInterpolator; 9 import android.view.animation.AlphaAnimation; 10 import android.view.animation.Animation; 11 import android.view.animation.Animation.AnimationListener; 12 import android.view.animation.AnimationUtils; 13 import android.widget.ImageView; 14 import android.widget.RelativeLayout; 15 16 import com.charon.rocketfly.setvice.RocketService; 17 import com.charon.rocketfly.util.ServiceUtil; 18 19 /** 20 * 小火箭升空界面 21 * @author dr 22 */ 23 public class RocketActivity extends Activity { 25 protected static final String TAG = "RocketActivity"; 27 private ImageView iv_rocket; 28 private ImageView iv_cloud; 29 private ImageView iv_cloud_line; 30 private RelativeLayout rl_cloud; 31 32 private AnimationDrawable fireAnimationDrawable; 33 34 @Override 35 protected void onCreate(Bundle savedInstanceState) { 36 super.onCreate(savedInstanceState); 37 setContentView(R.layout.activity_rocket); 38 findView(); 39 initView(); 40 } 41 42 private void findView() { 43 iv_rocket = (ImageView) findViewById(R.id.iv_rocket); 44 iv_cloud = (ImageView) findViewById(R.id.iv_cloud); 45 iv_cloud_line = (ImageView) findViewById(R.id.iv_cloud_line); 46 rl_cloud = (RelativeLayout) findViewById(R.id.rl_cloud); 47 } 48 49 private void initView() { 50 iv_rocket.setPressed(true); 51 iv_rocket.setFocusable(true); 52 iv_rocket.setVisibility(View.VISIBLE); 53 } 54 55 @Override 56 protected void onStart() { 57 super.onStart(); 58 iv_rocket.setBackgroundResource(R.drawable.rocket_fire); 59 fireAnimationDrawable = (AnimationDrawable) iv_rocket.getBackground(); 60 fireAnimationDrawable.start(); 61 62 fly(); 63 } 64 65 /** 66 * 火箭飞起来的动画,同时下方播放冒烟的动画 67 */ 68 private void fly() { 69 Log.e(TAG, "fly...."); 70 Animation animation = AnimationUtils.loadAnimation( 71 this.getApplicationContext(), R.anim.rocket_up); 72 animation.setFillAfter(true); 73 74 animation.setAnimationListener(new AnimationListener() { 75 76 @Override 77 public void onAnimationStart(Animation animation) { 78 // 开始发射的时候去博凡动画 79 MediaPlayer player = MediaPlayer.create(RocketActivity.this, 80 R.raw.rocket); 81 player.setLooping(false); 82 player.setVolume(1.0f, 1.0f); 83 player.start(); 84 85 AlphaAnimation cloudAppearAnimation = new AlphaAnimation(0.1f, 86 1.0f); 87 cloudAppearAnimation.setDuration(500); 88 89 Animation appearAnimation = new AlphaAnimation(0.0f, 1.0f); 90 appearAnimation.setDuration(500); 91 appearAnimation.setStartOffset(250); 92 93 iv_cloud.startAnimation(cloudAppearAnimation); 94 iv_cloud_line.startAnimation(appearAnimation); 95 } 96 97 @Override 98 public void onAnimationRepeat(Animation animation) { 99 } 100 101 @Override 102 public void onAnimationEnd(Animation animation) { 103 // 火箭播放完成后就去把云彩都消失 104 removeClound(); 105 if (!ServiceUtil.isServiceRunning(RocketActivity.this, 106 RocketService.class)) { 107 startService(new Intent(RocketActivity.this 108 .getApplicationContext(), RocketService.class)); 109 } 110 } 111 }); 112 113 iv_rocket.startAnimation(animation); 114 115 createClound(); 116 } 117 118 private void createClound() { 119 iv_cloud.setVisibility(View.VISIBLE); 120 iv_cloud_line.setVisibility(View.VISIBLE); 121 } 122 123 private void removeClound() { 124 AlphaAnimation disappearAnimation = new AlphaAnimation(1.0f, 0.0f); 125 disappearAnimation.setDuration(1000); 126 disappearAnimation.setFillAfter(true); 127 disappearAnimation 128 .setInterpolator(new AccelerateDecelerateInterpolator()); 129 130 disappearAnimation.setAnimationListener(new AnimationListener() { 131 132 @Override 133 public void onAnimationStart(Animation animation) { 135 } 136 137 @Override 138 public void onAnimationRepeat(Animation animation) { 140 } 141 142 @Override 143 public void onAnimationEnd(Animation animation) { 144 iv_rocket.setVisibility(View.GONE); 145 iv_cloud.setVisibility(View.GONE); 146 iv_cloud_line.setVisibility(View.GONE); 147 148 finish(); 149 } 150 }); 151 rl_cloud.startAnimation(disappearAnimation); 152 } 153 }
1 <?xml version="1.0" encoding="utf-8"?> 2 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 3 package="com.charon.rocketfly" 4 android:versionCode="1" 5 android:versionName="1.0" > 6 7 <uses-sdk 8 android:minSdkVersion="8" 9 android:targetSdkVersion="19" /> 10 11 <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> 12 <!-- 震动 --> 13 <uses-permission android:name="android.permission.VIBRATE" /> 14 <uses-permission android:name="android.permission.GET_TASKS"/> 15 16 <application 17 android:allowBackup="true" 18 android:icon="@drawable/ic_launcher" 19 android:label="@string/app_name" 20 android:theme="@style/AppTheme" > 21 <activity 22 android:name="com.charon.rocketfly.MainActivity" 23 android:label="@string/app_name" > 24 <intent-filter> 25 <action android:name="android.intent.action.MAIN" /> 26 <category android:name="android.intent.category.LAUNCHER" /> 27 </intent-filter> 28 </activity> 29 30 <activity 31 android:name="com.charon.rocketfly.RocketActivity" 32 android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen" /> 33 <service android:name="com.charon.rocketfly.setvice.RocketService" /> 34 35 </application> 36 37 </manifest>
DEMO下载地址:http://download.csdn.net/detail/androidsj/7952437