in this article I implement:
USE Andriod studio project & source code download:
GitHub:https://github.com/agathakuan/Andorid-Background-execution-double-service
GitHub:https://github.com/agathakuan/Andorid-Background-execution-double-service
Figure:
1.services communicate with Broadcast2.services send different actions Broadcast to activity3.HOW to make a broadcast receiver in service4.after Android 8.0(Oreo), how to send a system Notification(in NotificationHelper.java)5.HOW to implement a sensor-listening class(in ShakeListener.java)
My structure of ShakingWarning app:
1.main Activity only for maintain GUI
2.Input service for active listening to hardware sensor
(accelerometer for example)
3.Output service for send warning messenge by system notification.
4.if trigger shaking event,Input service send broadcast to main activity & Output service
- main activity will show Toast after receive broadcast from input service.
- if main activity is onPause,output service still working in background,which can send system notification.
Main source code
AndroidManifest.xml
user-permission for system notification VIBRATE<uses-permission android:name="android.permission.VIBRATE"/>
register input & output service
<service android:name=".outputService" android:enabled="true" android:exported="true"></service> <service android:name=".inputService" android:enabled="true" android:exported="true" />
MainActivity.java
connect to 2 services (input &output)
private ServiceConnection inputConnect = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { inputBinder =(inputService.inputBinder) service; inputBinder.startInput(); printInputServiceInfo("onInputServiceConnected ..."); } @Override public void onServiceDisconnected(ComponentName name) { printInputServiceInfo("onInputServiceDisconnected ..."); } }; private ServiceConnection outputConnect = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { outputBinder = (outputService.outputBinder) service; outputBinder.startOutput(); printOutputServiceInfo("onOutputServiceConnected ..."); } @Override public void onServiceDisconnected(ComponentName name) { printOutputServiceInfo("onOutputServiceDisconnected ..."); } };
onDestroy disconnect 2 services
@Override protected void onDestroy() { Intent mInputService_stop = new Intent(this, inputService.class); stopService(mInputService_stop); Intent mOutputService_stop = new Intent(this, outputService.class); stopService(mOutputService_stop); localBroadcastManager.unregisterReceiver(localReceiver); super.onDestroy(); }
input service receiver
//https://www.truiton.com/2014/09/android-service-broadcastreceiver-example/ private IntentFilter mInputIntentFilter; private BroadcastReceiver mInputReceiver; public static final String mInputBroadcastStringAction = "com.agathakuannewgmail.doubleservicetest.inputstring"; public static final String mInputBroadcastIntAction = "com.agathakuannewgmail.doubleservicetest.inputint"; public static final String mInputBroadcastArrayListAction = "com.agathakuannewgmail.doubleservicetest.inputarraylist";
mInputIntentFilter = new IntentFilter(); mInputIntentFilter.addAction(mInputBroadcastStringAction); mInputIntentFilter.addAction(mInputBroadcastIntAction); mInputIntentFilter.addAction(mInputBroadcastArrayListAction); mInputReceiver = new inputserviceReceiver();
class inputserviceReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if(intent.getAction().equals(mInputBroadcastIntAction)) { Toast.makeText(context, "received:"+String.valueOf(intent.getIntExtra("Data", 0)), Toast.LENGTH_SHORT).show(); } } }
inputService.java
Thread:listen to ShakeListener
ShakeListener mShakeListener = null;
@Override public void onCreate() { super.onCreate(); inputHandler = new Handler(); mShakeListener = new ShakeListener(this); mShakeListener.setOnShakeListener(new ShakeListener.OnShakeListener() { public void onShake() { mShakeListener.stop(); new Handler().postDelayed(new Runnable() { @Override public void run() { Intent broadcast2OutputService = new Intent(); broadcast2OutputService.setAction(outputService.mInputBroadcastStringAction); broadcast2OutputService.putExtra("Data","shaking!!"); sendBroadcast(broadcast2OutputService); mShakeListener.start(); } },600); } }); } @Override public void onDestroy() { if(mShakeListener != null) { mShakeListener.stop(); } super.onDestroy(); }
outputService.java
broadcast receiver of input service
private IntentFilter mInputIntentFilter; private BroadcastReceiver mInputReceiver; public static final String mInputBroadcastStringAction = "com.agathakuannewgmail.doubleservicetest.inputstring";
@Override public void onCreate() { super.onCreate(); mInputIntentFilter = new IntentFilter(); mInputIntentFilter.addAction(mInputBroadcastStringAction); mInputReceiver = new inputReceiver(); //https://blog.csdn.net/jdsjlzx/article/details/84327815 mNotificationHelper = new NotificationHelper(this); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d(TAG, "onStartCommand() executed by Alex"); registerReceiver(mInputReceiver, mInputIntentFilter); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { stopTimer(); unregisterReceiver(mInputReceiver); super.onDestroy(); }
public class inputReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(mInputBroadcastStringAction)) { Log.d("in inputReceiver",intent.getStringExtra("Data")); showNotification("From outputService",intent.getStringExtra("Data") ); } } }
NotificationHelper.java
package com.agathakuannewgmail.doubleservicetest; import android.content.ContextWrapper; import android.app.NotificationChannel; import android.app.NotificationManager; import android.content.Context; import android.content.ContextWrapper; import android.content.Intent; import android.content.pm.PackageManager; import android.graphics.BitmapFactory; import android.os.Build; import android.provider.Settings; import android.support.v4.app.NotificationCompat; import java.text.SimpleDateFormat; import java.util.Date; import android.graphics.Color; //https://blog.csdn.net/jdsjlzx/article/details/84327815\ //https://github.com/XuMiaoLee/AndroidNotificationChannel public class NotificationHelper extends ContextWrapper{ private NotificationManager mNotificationManager; private NotificationChannel mNotificationChannel; public static final String CHANNEL_ID = "default"; private static final String CHANNEL_NAME = "Default Channel"; private static final String CHANNEL_DESCRIPTION = "this is default channel!"; private SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");// HH:mm:ss private Date date = new Date(System.currentTimeMillis()); public NotificationHelper(Context base) { super(base); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { mNotificationChannel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT); mNotificationChannel.setDescription(CHANNEL_DESCRIPTION); mNotificationChannel.enableLights(true); mNotificationChannel.setLightColor(Color.BLUE); mNotificationChannel.setShowBadge(true); mNotificationChannel.setBypassDnd(true); mNotificationChannel.setVibrationPattern(new long[]{100, 100, 200}); mNotificationChannel.shouldShowLights(); getNotificationManager().createNotificationChannel(mNotificationChannel); } } public NotificationCompat.Builder getNotification(String title, String content) { NotificationCompat.Builder builder = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { builder = new NotificationCompat.Builder(this, CHANNEL_ID); } else { builder = new NotificationCompat.Builder(this); builder.setPriority(NotificationCompat.PRIORITY_MAX); } builder.setContentTitle(title); builder.setContentText(content+" "+"at"+" "+simpleDateFormat.format(date)); builder.setSmallIcon(R.mipmap.comments); builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.comments)); builder.setVibrate(new long[]{0,1000,1000,1000}); builder.setLights(Color.BLUE, 1000,200); //builder.setDefaults(NotificationCompat.DEFAULT_ALL); builder.setAutoCancel(true);//点击自动删除通知 return builder; } public void notify(int id, NotificationCompat.Builder builder) { if (getNotificationManager() != null) { getNotificationManager().notify(id, builder.build()); } } private NotificationManager getNotificationManager() { if (mNotificationManager == null) mNotificationManager = (NotificationManager) this.getSystemService(this.NOTIFICATION_SERVICE); return mNotificationManager; } }
ShakeListener.java
REFERENCE:
https://blog.csdn.net/guolin_blog/article/details/11952435
https://blog.csdn.net/qq_31939617/article/details/80118302
package com.agathakuannewgmail.doubleservicetest; import android.content.Context; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.util.Log; public class ShakeListener implements SensorEventListener { private static final int SPEED_THERSHOLD = 3000; private static final int UPDATE_INTERVAL = 70; private SensorManager sensorManager; private Sensor sensor; private OnShakeListener onShakeListener; private Context mContext; private float last_x, last_y, last_z; private long update_time; public ShakeListener(Context c) { mContext = c; start(); } public void start() { sensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE); if(sensorManager != null) { sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); } if(sensor != null) { sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_GAME); } } public void stop() { sensorManager.unregisterListener(this); } public void setOnShakeListener(OnShakeListener listener) { onShakeListener = listener; } @Override public void onSensorChanged(SensorEvent event) { long currentUpdateTime = System.currentTimeMillis(); long timeInterval = currentUpdateTime - update_time; if(timeInterval <UPDATE_INTERVAL)return; update_time = currentUpdateTime; float x = event.values[0]; float y = event.values[1]; float z = event.values[2]; float deltaX = x -last_x; float deltaY = x -last_y; float deltaZ = x -last_z; last_x = x; last_y = y; last_z = z; double speed = Math.sqrt(deltaX*deltaX+ deltaY*deltaY+ deltaZ*deltaZ)/timeInterval*10000; Log.d("ShakeListener", String.valueOf(x)+String.valueOf(y)+String.valueOf(z)); if(speed >= SPEED_THERSHOLD) { onShakeListener.onShake(); } } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } public interface OnShakeListener { public void onShake(); } }
REFERENCE:
https://blog.csdn.net/guolin_blog/article/details/11952435
https://blog.csdn.net/qq_31939617/article/details/80118302
沒有留言:
張貼留言