前言:
近期在写一个小程序,需求是手机摇一摇就弹窗出来。第一次使用了Service,学习了两天,实现了Service弹窗,开机启动,Service启动和销毁,Service保持一直执行。
满足了自己的需求。现记录学习心得。
希望能给你带来一些帮助。
1.Service创建:重写4个方法
- onBind():返回一个IBinder对象,这个对象能够使应用程序与Service通信。假设用startService、stopService启动和关闭Service的话。Service和訪问者是无法通信交换数据的。onBind()返回值设为null就可以。
可是假设想要交换数据,就要用bindService、unbindService来启动和关闭Service。这时,onBind()要返回一个有效的IBinder对象。
- onCreate():Service第一次被创建时调用此方法。
- onStartCommand():理解为onStart()的新一代。每次通过startService(Intent)启动Service时都会调用此方法。
- onDestroy():Service被关闭之前调用此方法。
package com.service; import android.app.Service; import android.content.Context; import android.content.Intent; import android.util.Log; public class PopupService extends Service { @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return null; } @Override public void onCreate() { super.onCreate(); System.out.println("Service is Created"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { System.out.println("Service is Started"); return START_STICKY; } @Override public void onDestroy() { super.onDestroy(); System.out.println("Service is Destroyed"); } }
2.Service配置:在AndroidManifest.xml中声明
<service android:name="com.service.PopupService" android:priority = "1000" <!-- 提高优先级--> android:persistent="true"> <!-- 免杀,不知道有没有起作用--> <intent-filter> <action android:name="com.service.POPUP_SERVICE" /> </intent-filter> </service>
3.Service开机启动:使用BroadcastReceiver
文件创建:
package com.service; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; public class StartupReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // 启动一个Service Intent serviceIntent = new Intent(context, PopupService.class); context.startService(serviceIntent); } }
文件配置:在AndroidManifest.xml中声明
<receiver android:name="com.service.StartupReceiver"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </receiver>
注意权限:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
4.Service从Activity中启动:
在主Activity中使用startService(Intent)
Intent popupintent=new Intent(); popupintent.setAction("com.service.POPUP_SERVICE"); startService(popupintent);
5.Service监听重力感应而且弹窗:
- 这里使用Sensor.TYPE_ACCELEROMETER加速度感应器。和其它监听器比方手势等一样,包含声明、注冊、监听等
- 弹窗使用的是theme定义为dialog。notitle的activity。
弹窗相关代码:
Intent activityIntent = new Intent(this, SelectFriendsActivity.class); //要想在Service中启动Activity,必须设置例如以下标志 activityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(activityIntent);
完整代码:
package com.service; import com.task.SelectFriendsActivity; import android.app.Service; import android.content.Context; import android.content.Intent; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.os.IBinder; import android.os.Vibrator; import android.util.Log; public class PopupService extends Service implements SensorEventListener{ //sensorManager private SensorManager sensorManager; private Vibrator vibrator; Intent activityIntent; @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return null; } @Override public void onCreate() { super.onCreate(); System.out.println("Service is Created"); sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); } @Override public int onStartCommand(Intent intent, int flags, int startId) { System.out.println("Service is Started"); //启动service,将serviceon置为TRUE,可弹窗。 SelectFriendsActivity.serviceon = true; if (sensorManager != null) {// 注冊监听器 sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL); // 第一个參数是Listener。第二个參数是所得传感器类型。第三个參数值获取传感器信息的频率 } activityIntent = new Intent(this, SelectFriendsActivity.class); // 要想在Service中启动Activity,必须设置例如以下标志 activityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); return START_STICKY; } @Override public void onDestroy() { super.onDestroy(); System.out.println("Service is Destroyed"); } /** * 重力感应监听 */ public void onSensorChanged(SensorEvent event) { // 传感器信息改变时运行该方法 float[] values = event.values; float x = values[0]; // x轴方向的重力加速度,向右为正 float y = values[1]; // y轴方向的重力加速度。向前为正 float z = values[2]; // z轴方向的重力加速度,向上为正 Log.i("group", "x轴方向的重力加速度" + x + ";y轴方向的重力加速度" + y + "。z轴方向的重力加速度" + z); // 一般在这三个方向的重力加速度达到40就达到了摇晃手机的状态。 int medumValue = 19;// 三星 i9250怎么晃都不会超过20,没办法。仅仅设置19了 if (Math.abs(x) > medumValue || Math.abs(y) > medumValue || Math.abs(z) > medumValue) { if(SelectFriendsActivity.serviceon){ vibrator.vibrate(200); System.out.println("Service:shaked and popup!!!!!!!"); startActivity(activityIntent); }else{ System.out.println("Service:shaked only!!!!!!!"); } } } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } }
弹出的Activity就是一般的Activity,仅仅只是要在其xml中设置其大小,在AndroidManifest.xml中将其theme设置为notitle。dialog类型
能够使用这个style:
<style name="dialogTheme" parent="android:Theme.Dialog"> <item name="android:windowNoTitle">true</item> </style>
弹窗要求加入权限:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
6.Service 保持一直执行,不被杀死
的方法:
重写onDestroy():
@Override public void onDestroy() { // super.onDestroy(); // System.out.println("Service is Destroyed"); System.out.println("Service is Destroyed,and is Restarted"); Intent localIntent = new Intent(); localIntent.setClass(this, PopupService.class); //销毁时又一次启动 Service this.startService(localIntent); }
这样不管怎样Service都一直在后台执行了。
7.图文记录:
7.1 启动app,MainActivity中调用了startService(popupintent);
结果:说明依次调用了Service中的onCreate()、onStartCommand()方法,Service開始执行
7.2 震动手机,Service响应弹窗
结果:弹窗,Service正常执行,重力感应器正常执行
7.3 杀死应用进程,震动手机,Service仍然响应弹窗
结果:弹窗,说明尽管应用进程被杀死,可是Service仍保持正常执行,重力感应器正常执行
7.4 点击弹窗的Avtivity中的button,button监听代码:
Intent popupintent=new Intent(); popupintent.setAction("com.service.POPUP_SERVICE"); stopService(popupintent);
即调用了stopService(Intent) 方法
结果:打印出Service
is Destroyed,说明调用了Service的onDestroy()方法
7.5
再次震动手机,发现还是有打印输出:
结果:说名尽管调用了onDestroy()方法。可是其Context未被清除,Service仍然存在
7.6
杀死全部有关此弹窗的进程。再次震动手机。发现没有打印输出了:
结果:一旦其Context被全然清除。Service就真正停止了。
感谢newcj
的博客 文章 Android
中的 Service 全面总结
让我受益匪浅。大家能够去看看,评论区非常精彩:
第一次学着用Service,文中假设有错误请大家指正。
版权声明:本文博客原创文章,博客,未经同意,不得转载。