package org.droidplanner.android;
import android.annotation.TargetApi;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
import android.support.v4.content.LocalBroadcastManager;
import com.o3dr.android.client.Drone;
import com.o3dr.services.android.lib.drone.attribute.AttributeEvent;
import com.o3dr.services.android.lib.drone.attribute.AttributeEventExtra;
import org.droidplanner.android.notifications.NotificationHandler;
import org.droidplanner.android.utils.NetworkUtils;
import org.droidplanner.android.utils.analytics.GAUtils;
import timber.log.Timber;
/**
* Created by Fredia Huya-Kouadio on 9/28/15.
*/
public class AppService extends Service {
private static final IntentFilter filter = new IntentFilter();
static {
filter.addAction(AttributeEvent.STATE_CONNECTED);
filter.addAction(AttributeEvent.STATE_DISCONNECTED);
filter.addAction(AttributeEvent.AUTOPILOT_ERROR);
}
private final BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
switch (intent.getAction()) {
case AttributeEvent.STATE_CONNECTED:
if (notificationHandler != null)
notificationHandler.init();
if (NetworkUtils.isOnSoloNetwork(context)) {
bringUpCellularNetwork();
}
break;
case AttributeEvent.STATE_DISCONNECTED:
if (notificationHandler != null) {
notificationHandler.terminate();
}
stopSelf();
break;
case AttributeEvent.AUTOPILOT_ERROR:
final String errorName = intent.getStringExtra(AttributeEventExtra.EXTRA_AUTOPILOT_ERROR_ID);
if (notificationHandler != null)
notificationHandler.onAutopilotError(errorName);
break;
}
}
};
private final BinderHandler binderHandler = new BinderHandler();
private NotificationHandler notificationHandler;
private DroidPlannerApp dpApp;
private Drone drone;
@Override
public void onCreate() {
super.onCreate();
dpApp = (DroidPlannerApp) getApplication();
dpApp.createFileStartLogging();
dpApp.getSoundManager().start();
drone = dpApp.getDrone();
final Context context = getApplicationContext();
if (NetworkUtils.isOnSoloNetwork(context)) {
bringUpCellularNetwork();
}
GAUtils.initGATracker(dpApp);
GAUtils.startNewSession(context);
notificationHandler = new NotificationHandler(context, drone);
if (drone.isConnected()) {
notificationHandler.init();
}
LocalBroadcastManager.getInstance(context).registerReceiver(receiver, filter);
}
@Override
public void onDestroy() {
super.onDestroy();
LocalBroadcastManager.getInstance(getApplicationContext()).unregisterReceiver(receiver);
if (notificationHandler != null)
notificationHandler.terminate();
dpApp.getSoundManager().stop();
bringDownCellularNetwork();
dpApp.closeLogFile();
}
@Override
public IBinder onBind(Intent intent) {
return binderHandler;
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void bringUpCellularNetwork() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
return;
// Wait until the drone is connected.
if(drone == null || !drone.isConnected())
return;
Timber.i("Setting up cellular network request.");
final ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
final NetworkRequest networkReq = new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
.build();
connMgr.requestNetwork(networkReq, new ConnectivityManager.NetworkCallback() {
@Override
public void onAvailable(Network network) {
Timber.i("Setting up process default network: %s", network);
boolean wasBound;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
wasBound = connMgr.bindProcessToNetwork(network);
} else {
wasBound = ConnectivityManager.setProcessDefaultNetwork(network);
}
DroidPlannerApp.setCellularNetworkAvailability(wasBound);
}
});
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void bringDownCellularNetwork() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
return;
Timber.i("Bringing down cellular netowrk access.");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
final ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
connMgr.bindProcessToNetwork(null);
} else {
ConnectivityManager.setProcessDefaultNetwork(null);
}
ConnectivityManager.setProcessDefaultNetwork(null);
DroidPlannerApp.setCellularNetworkAvailability(false);
}
public static class BinderHandler extends Binder {
}
}