io.v.location.LocationService.java Source code

Java tutorial

Introduction

Here is the source code for io.v.location.LocationService.java

Source

// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package io.v.location;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationManager;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;

import com.google.common.collect.Lists;

import java.util.Arrays;
import java.util.List;

import io.v.android.v23.V;
import io.v.v23.context.VContext;
import io.v.v23.rpc.ListenSpec;
import io.v.v23.rpc.Server;
import io.v.v23.rpc.ServerCall;
import io.v.v23.security.BlessingPattern;
import io.v.v23.security.Blessings;
import io.v.v23.security.VCertificate;
import io.v.v23.security.VPrincipal;
import io.v.v23.security.VSecurity;
import io.v.v23.verror.VException;
import io.v.v23.vom.VomUtil;

public class LocationService extends Service {
    private static final String TAG = "LocationService";

    VContext mBaseContext;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        mBaseContext = V.init(this);
        String blessingsVom = intent.getStringExtra(LocationActivity.BLESSINGS_KEY);
        if (blessingsVom == null || blessingsVom.isEmpty()) {
            String msg = "Couldn't start LocationService: null or empty encoded blessings.";
            Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
            Log.i(TAG, msg);
            return START_REDELIVER_INTENT;
        }
        try {
            Blessings blessings = (Blessings) VomUtil.decodeFromString(blessingsVom, Blessings.class);
            if (blessings == null) {
                String msg = "Couldn't start LocationService: null blessings.";
                Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
                Log.i(TAG, msg);
                return START_REDELIVER_INTENT;
            }
            storeBlessings(blessings);
            startLocationService(determineMountPoint(blessings));
        } catch (VException e) {
            String msg = "Couldn't start LocationService: " + e.getMessage();
            Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
            Log.i(TAG, msg);
        }
        return START_REDELIVER_INTENT;
    }

    private void startLocationService(String mountPoint) throws VException {
        VeyronLocationService locationService = new VeyronLocationService(
                (LocationManager) getSystemService(Context.LOCATION_SERVICE));
        ListenSpec spec = V.getListenSpec(mBaseContext).withProxy("proxy");
        Log.i(TAG, "Mounting server at " + mountPoint);
        VContext ctx = V.withNewServer(V.withListenSpec(mBaseContext, spec), mountPoint, locationService, null);
        Server server = V.getServer(ctx);
        Log.i(TAG, "Listening on endpoints: " + Arrays.toString(server.getStatus().getEndpoints()));
        Toast.makeText(this, "Success", Toast.LENGTH_SHORT).show();
    }

    // Update vanadium state with the new blessings.
    private void storeBlessings(Blessings blessings) throws VException {
        VPrincipal p = V.getPrincipal(mBaseContext);
        p.blessingStore().setDefaultBlessings(blessings);
        p.blessingStore().set(blessings, new BlessingPattern("..."));
        VSecurity.addToRoots(p, blessings);
    }

    @Override
    public IBinder onBind(Intent intent) {
        // Binding not allowed.
        return null;
    }

    private static class VeyronLocationService implements LocationServer {
        private final LocationManager manager;

        private VeyronLocationService(LocationManager manager) {
            this.manager = manager;
        }

        @Override
        public LatLng get(VContext context, ServerCall call) throws VException {
            Criteria criteria = new Criteria();
            criteria.setAccuracy(Criteria.NO_REQUIREMENT);
            String provider = manager.getBestProvider(criteria, true);
            if (provider == null || provider.isEmpty()) {
                throw new VException("Couldn't find any location providers on the device.");
            }
            Location location = manager.getLastKnownLocation(provider);
            if (location == null) {
                throw new VException("Got null location.");
            }
            return new LatLng(location.getLatitude(), location.getLongitude());
        }
    }

    private static String determineMountPoint(Blessings blessings) {
        String name = userEmailFromBlessings(blessings);
        return name.isEmpty() ? "" : "users/" + name + "/location";
    }

    private static String userEmailFromBlessings(Blessings blessings) {
        for (List<VCertificate> chain : blessings.getCertificateChains()) {
            for (VCertificate certificate : Lists.reverse(chain)) {
                if (certificate.getExtension().contains("@")) {
                    return certificate.getExtension();
                }
            }
        }
        Log.w(TAG, "Could not determine name from blessings '" + blessings + "'");
        return "";
    }
}