package com.maciekjanusz.compassproject.ui;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.hardware.display.DisplayManager;
import android.os.Build;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.Gravity;
import android.view.View;
import android.view.WindowManager;
import android.widget.LinearLayout;
import com.maciekjanusz.compassproject.sensor.Compass;
import com.maciekjanusz.compassproject.navigation.NavigationBundle;
import com.maciekjanusz.compassproject.navigation.ServiceMessage;
import com.maciekjanusz.compassproject.navigation.ServiceState;
import com.maciekjanusz.compassproject.util.ScreenRotationAware;
import com.maciekjanusz.compassproject.util.SimpleDisplayListener;
import com.maciekjanusz.draglayout.DragLayout;
import de.greenrobot.event.EventBus;
import static com.maciekjanusz.compassproject.preferences.AppPreferences.WIDGET_SERVICE_RUNNING;
import static com.maciekjanusz.compassproject.util.CompassMath.adjustBearing;
public class ScreenWidgetService extends Service implements DragLayout.DragListener,
Compass.CompassListener, ScreenRotationAware {
private static final int SIZE_DP = 96;
private static final int WIDGET_SCALE_LINES = 72;
private WindowManager.LayoutParams params;
private WindowManager windowManager;
private DisplayManager displayManager;
private DragLayout dragLayout;
private CompassView compassView;
private Compass compass;
private float currentRoll;
private volatile int rotation;
private boolean started;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
compass = new Compass(this, this);
initParams();
initViews();
}
private DisplayManager.DisplayListener displayListener = new SimpleDisplayListener() {
@Override
public void onDisplayChanged(int displayId) {
updateRotation();
}
};
private void initViews() {
int sizePx = dpToPx(SIZE_DP);
windowManager = ((WindowManager) getApplicationContext().
getSystemService(Context.WINDOW_SERVICE));
displayManager = ((DisplayManager) getApplicationContext()
.getSystemService(Context.DISPLAY_SERVICE));
displayManager.registerDisplayListener(displayListener, null);
updateRotation();
// init compass view
compassView = new CompassView(this);
compassView.setCompassEnabled(true);
compassView.setHasBackground(true);
compassView.setStrokeWidth(0);
compassView.setScaleLines(WIDGET_SCALE_LINES);
compassView.setLayoutParams(new LinearLayout.LayoutParams(sizePx, sizePx));
// init dragLayout & add compass view
dragLayout = new DragLayout(this);
dragLayout.addView(compassView);
dragLayout.setDragListener(this);
dragLayout.setInitialPosition(params.x, params.y);
dragLayout.setScale(-0.25f);
dragLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent activityIntent = new Intent(ScreenWidgetService.this, CompassActivity.class);
activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(activityIntent);
}
});
}
private void initParams() {
int paramFlags = WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
paramFlags |= WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION
| WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
}
params = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_PHONE,
paramFlags,
PixelFormat.TRANSLUCENT);
params.gravity = Gravity.TOP;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(!started) {
compass.start();
// check navigation service status
EventBus.getDefault().register(this);
EventBus.getDefault().post(ServiceMessage.REQUEST_NAVIGATION_SERVICE_STATE);
// display compass on screen
displayOverlayView(params);
saveRunningPref(true);
started = true;
}
return START_STICKY;
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// update screen rotation
updateRotation();
}
@Override
public synchronized void updateRotation() {
rotation = windowManager.getDefaultDisplay().getRotation();
}
@Override
public void onDestroy() {
compass.stop();
displayManager.unregisterDisplayListener(displayListener);
removeOverlayView();
EventBus.getDefault().unregister(this);
saveRunningPref(false);
started = false;
super.onDestroy();
}
private void saveRunningPref(boolean running) {
PreferenceManager
.getDefaultSharedPreferences(this)
.edit()
.putBoolean(WIDGET_SERVICE_RUNNING, running)
.commit();
}
private void displayOverlayView(WindowManager.LayoutParams params) {
if(dragLayout != null && !(dragLayout.isShown())) {
windowManager.addView(dragLayout, params);
}
}
private void removeOverlayView() {
if(dragLayout != null && dragLayout.isShown()) {
windowManager.removeView(dragLayout);
}
}
@Override
public void onDragFinished(float x, float y) {
updateViewPosition(x, y);
}
@Override
public void onDrag(float x, float y) {
updateViewPosition(x, y);
}
@Override
public void onDragStarted(float x, float y) {
updateViewPosition(x, y);
}
private void updateViewPosition(float x, float y) {
params.x = (int) x;
params.y = (int) y;
windowManager.updateViewLayout(dragLayout, params);
}
@Override
public void onCompassStateChanged(float bearing, float pitch, float roll) {
currentRoll = roll;
bearing = adjustBearing(bearing, roll, rotation);
compassView.setCompassBearing(-bearing);
compassView.invalidate();
}
@SuppressWarnings("unused")
public void onEvent(NavigationBundle navigationBundle) {
float bearing = navigationBundle.getBearing();
bearing = adjustBearing(bearing, currentRoll, 0);
compassView.setNavigationBearing(bearing);
compassView.setNavigationEnabled(true);
}
@SuppressWarnings("unused")
public void onEvent(@NonNull ServiceState serviceState) {
switch(serviceState) {
case NAVIGATION_RUNNING:
// nothing
break;
case NAVIGATION_STOPPED:
compassView.setNavigationEnabled(false);
break;
}
}
private int dpToPx(int dp) {
DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
return Math.round(dp * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));
}
}