GPSの研究　その15

#概要
GPSを理解したかった。
android1.6で、天空図を書いてみた。

#写真
![device-2018-06-18-131341.png](https://qiita-image-store.s3.amazonaws.com/0/18104/1e514db9-db4d-109d-1337-b985a959eb5d.png)



#サンプルコード

```
package com.ohisamllc.ohiapp33;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.location.GpsSatellite;
import android.location.GpsStatus;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.location.GpsStatus.Listener;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TableLayout;

public class ohiapp33 extends Activity implements LocationListener, Listener
{
	static final int NUM_SATS = 32;
	public static final class GpsInfo
	{
		GpsInfo(int prn)
		{
			this.prn = prn;
			this.name = "" + prn;
		}
		final int prn;
		final String name;
		long time = 0;
		float azimuth;
		float elev;
		float snr;
		boolean hasAl;
		boolean hasEph;
		boolean used;
		long usedTime = 0;
		RectF rect;
		float textX;
		float textY;
		int colour;
	}
	private static final String TAG = "ohiapp33";
	private static final String[] locationProviders = {
		LocationManager.NETWORK_PROVIDER,
		LocationManager.GPS_PROVIDER
	};
	private static final int[] COLOUR_PLOT = {
		0xff00ffff,
		0xff00ff00,
		0xffffff00,
		0xffff9000,
	};
	private static final int DATA_CACHE_TIME = 10 * 1000;
	private LocationManager locationManager;
	private GpsStatus gpsStatus = null;
	public  GpsInfo[] satCache;
	private int numSats;
	private final String msgOffline = "";
	private rdView  rdView;
	@Override public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		rdView = new rdView(this);
		setContentView(rdView);
		satCache = new GpsInfo[NUM_SATS + 1];
		for (int i = 1; i <= NUM_SATS; ++i)  satCache[i] = new GpsInfo(i);
		numSats = 0;
		locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
		for (String name : locationProviders)
		{
			LocationProvider prov = locationManager.getProvider(name);
			if (prov != null)
			{
				locationManager.requestLocationUpdates(name, 60000, 0f, this);
				if (name.equals(LocationManager.GPS_PROVIDER)) locationManager.addGpsStatusListener(this);
				Location prime = locationManager.getLastKnownLocation(name);
				if (prime != null)  onLocationChanged(prime);
			}
		}
	}
	@Override public void onDestroy()
	{
		locationManager.removeUpdates(this);
		locationManager.removeGpsStatusListener(this);
		locationManager = null;
		super.onDestroy();
	}
	public void onLocationChanged(Location loc)
	{
		synchronized (this)
		{
			if (loc.getProvider().equals(LocationManager.GPS_PROVIDER))
			{
				rdView.setloc(loc);
			}
		}
	}
	public void onProviderEnabled(String provider)
	{
		synchronized (this)
		{
			if (provider.equals(LocationManager.GPS_PROVIDER))
			{
			}
		}
	}
	public void onProviderDisabled(String provider)
	{
		synchronized (this)
		{
			if (provider.equals(LocationManager.GPS_PROVIDER))
			{
			}
		}
	}
	public void onStatusChanged(String provider, int status, Bundle extras)
	{
		synchronized (this)
		{
			String msg = null;
			if (status == LocationProvider.OUT_OF_SERVICE)
			{
				msg = msgOffline;
			}
			if (provider.equals(LocationManager.GPS_PROVIDER))
			{
			}
		}
	}
	public void onGpsStatusChanged(int event)
	{
		switch (event)
		{
		case GpsStatus.GPS_EVENT_SATELLITE_STATUS:
			gpsStatus = locationManager.getGpsStatus(gpsStatus);
			Iterable<GpsSatellite> sats = gpsStatus.getSatellites();
			long time = System.currentTimeMillis();
			for (GpsSatellite sat : sats)
			{
				int prn = sat.getPrn();
				if (prn < 1 || prn > NUM_SATS)  continue;
				GpsInfo ginfo = satCache[prn];
				ginfo.time = time;
				ginfo.azimuth = sat.getAzimuth();
				ginfo.elev = sat.getElevation();
				ginfo.snr = sat.getSnr();
				ginfo.hasAl = sat.hasAlmanac();
				ginfo.hasEph = sat.hasEphemeris();
				ginfo.used = sat.usedInFix();
			}
			numSats = 0;
			for (int prn = 1; prn <= NUM_SATS; ++prn)
			{
				GpsInfo ginfo = satCache[prn];
				if (time - ginfo.time > DATA_CACHE_TIME)
				{
					ginfo.time = 0;
					ginfo.usedTime = 0;
				}
				else
				{
					if (ginfo.used) ginfo.usedTime = time;
					else if (time - ginfo.usedTime <= DATA_CACHE_TIME) ginfo.used = true;
					else ginfo.usedTime = 0;
					int colour = ginfo.used ? 0 : ginfo.hasEph ? 1 : ginfo.hasAl ? 2 : 3;
					ginfo.colour = COLOUR_PLOT[colour];
					++numSats;
				}
			}
			rdView.setInfo(satCache);
			rdView.setflg(1);
			rdView.invalidate();
		break;
		case GpsStatus.GPS_EVENT_STARTED:
		case GpsStatus.GPS_EVENT_STOPPED:
		case GpsStatus.GPS_EVENT_FIRST_FIX:
		break;
		}
	}
}
class rdView extends View
{
	static final int NUM_SATS = 32;
	private ohiapp33.GpsInfo[] satCache;
	private int flg = 0;
	private Location loc;
	private Calendar calen = Calendar.getInstance();
	public rdView(Context context)
	{
		super(context);
	}
	public void setloc(Location loc)
	{
		this.loc = loc;
	}
	public void setInfo(ohiapp33.GpsInfo[] satCache)
	{
		this.satCache = satCache;
	}
	public void setflg(int flg)
	{
		this.flg = flg;
	}
	protected void onDraw(Canvas canvas)
	{
		Paint paint = new Paint();
		paint.setColor(Color.WHITE);
		paint.setStrokeWidth(2f);
		paint.setStyle(Paint.Style.STROKE);
		int centerX = this.getWidth() / 2;
		int centerY = this.getHeight() / 2;
		float maxRadius = (Math.min(this.getHeight(), this.getWidth()) - 20) / 2;
		double[] elevations = new double[] {
			0,
			Math.PI / 2,
			Math.PI / 3,
			Math.PI / 6
		};
		for (double elevation : elevations)
		{
			double radius = (double) Math.cos(elevation) * maxRadius;
			canvas.drawCircle((float) centerX, (float) centerY, (float) radius, paint);
		}
		canvas.drawLine(centerX - maxRadius, centerY, centerX + maxRadius, centerY, paint);
		canvas.drawLine(centerX, centerY - maxRadius, centerX, centerY + maxRadius, paint);
		canvas.drawText("N", centerX - 5, centerY - maxRadius, paint);
		canvas.drawText("S", centerX - 5, centerY + maxRadius + 10, paint);
		canvas.drawText("E", centerX + maxRadius + 5, centerY + 5, paint);
		canvas.drawText("W", centerX - maxRadius - 5, centerY + 5, paint);
		paint.setStyle(Paint.Style.FILL_AND_STROKE);
		paint.setTextSize(20);
		if (flg == 1)
		{
			for (int prn = 1; prn <= NUM_SATS; prn++)
			{
				ohiapp33.GpsInfo ginfo = this.satCache[prn];
				if (ginfo.azimuth != 0)
				{
					double h = (double) Math.cos((ginfo.elev * Math.PI) / 180) * maxRadius;
					int satX = (int) (centerX + h * Math.sin((ginfo.azimuth * Math.PI) / 180));
					int satY = (int) (centerY - h * Math.cos((ginfo.azimuth * Math.PI) / 180));
					paint.setColor(ginfo.colour);
					canvas.drawCircle(satX, satY, ginfo.snr / 3, paint);
				}
			}
			for (int prn = 1; prn <= NUM_SATS; prn++)
			{
				ohiapp33.GpsInfo ginfo = this.satCache[prn];
				if (ginfo.azimuth != 0)
				{
					double h = (double) Math.cos((ginfo.elev * Math.PI) / 180) * maxRadius;
					int satX = (int) (centerX + h * Math.sin((ginfo.azimuth * Math.PI) / 180));
					int satY = (int) (centerY - h * Math.cos((ginfo.azimuth * Math.PI) / 180));
					paint.setColor(Color.RED);
					canvas.drawText(ginfo.name, satX + 5, satY + 5, paint);
				}
			}
			if (loc != null)
			{
				paint.setColor(Color.YELLOW);
				String p;
				p = "Lat " + new Float(loc.getLatitude()).toString();
				canvas.drawText(p, 10, 40, paint);
				p = "Lon " + new Float(loc.getLongitude()).toString();
				canvas.drawText(p, 170, 40, paint);
				p = "Alt " + new Float(loc.getAltitude()).toString() + "m";
				canvas.drawText(p, 10, 390, paint);
				if (loc.getTime() > 0)
				{
					calen.setTimeInMillis(loc.getTime());
					SimpleDateFormat a = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
					canvas.drawText(a.format(calen.getTime()), 10, 420, paint);
				}
			}
		}
	}
}



```


以上。