gpx - это, по сути, особый xml. То, о чем вы говорите, это XML Пространство имен .
Как его создать: как создать XML заголовок
A Файл xml может иметь только один элемент root, но в файле gpx столько элементов trkpt
. Поэтому элемент trkpt
не должен быть элементом root. Вы должны включить все элементы trkpt
в один элемент gpx
, который является элементом root вашего файла gpx.
Для создания файла gpx в Android лучшим выбором будет использование библиотеки. Большинство из них могут помочь вам выполнить все вышеперечисленные операции.
Я использую io.jenetics.jpx
в своем проекте android, и он отлично работает.
XML не поддерживает добавляемые элементы. Если вы хотите сгенерировать файл gpx во время регистрации, вы должны сделать это в доступной форме, такой как любой тип Serializable
. После окончания регистрации вы можете создать действительный файл GPX из файла сериализации.
WayPoint
в jpx - это тип Serializable, я его использую.
Вы также можете использовать Android Location
, который реализует Parcelable
, реализацию android, такую как Serializable.
мой код:
public class TrackService extends Service {
private int notificationId = 142857 ;
NotificationCompat.Builder builder;
NotificationManagerCompat notificationManager;
private Timer timer = new Timer(true);
private static final String CHANNEL_ID = "org.kib.qtp";
private File serializerFile;
private ObjectOutputStream oos;
private Long basetime;
SimpleDateFormat sdf;
@Override
public void onCreate(){
super.onCreate();
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0);
builder = new NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_map_black_24dp)
.setContentTitle(getString(R.string.track))
.setContentText(getString(R.string.tracktext))
.setPriority(NotificationCompat.PRIORITY_LOW)
.setOngoing(true)
.setOnlyAlertOnce(true)
.setContentIntent(pendingIntent);
notificationManager = NotificationManagerCompat.from(this);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
startForeground (notificationId, builder.build());
else
notificationManager.notify(notificationId, builder.build());
}
@Override
public void onDestroy(){
try {
endTrack();
} catch (IOException e) {
e.printStackTrace();
}
stopForeground(true);
super.onDestroy();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId){
/**
* @param ele require altitude or not
* @param time update time
* @param fine fine location or not
* @param name the gpx file's name
*/
sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", getResources(). getConfiguration().locale);
int time = 60000;
boolean ele = false;
boolean fine = false;
String name = Calendar.getInstance().getTime().toString().replaceAll(" ", "_");
if (intent.hasExtra("time"))
Objects.requireNonNull(intent.getExtras()).getInt("time");
if (intent.hasExtra("ele"))
Objects.requireNonNull(intent.getExtras()).getBoolean("ele");
if (intent.hasExtra("fine"))
Objects.requireNonNull(intent.getExtras()).getBoolean("fine");
if (intent.hasExtra("name"))
Objects.requireNonNull(intent.getExtras()).getString("name");
File path = new File(getFilesDir().getAbsolutePath() + "/gpx");
while(!path.exists())
path.mkdirs();
try {
serializerFile = new File(getFilesDir().getAbsolutePath() + "/gpx/" + name );
if (serializerFile.exists())
serializerFile.delete();
while(!serializerFile.exists())
serializerFile.createNewFile();
oos = new ObjectOutputStream(new FileOutputStream(serializerFile));
} catch (IOException e) {
e.printStackTrace();
}
basetime = 0L;
Toast.makeText(this, R.string.toast_start_tracking, Toast.LENGTH_SHORT).show();
startTrack(time, ele, fine);
return START_STICKY;
}
private void endTrack() throws IOException {
timer.cancel();
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(serializerFile));
TrackSegment.Builder segment = TrackSegment.builder();
while (true) {
try{
WayPoint wp = (WayPoint) ois.readObject();
segment.addPoint(wp);
} catch (EOFException e) {
break;
} catch (ClassNotFoundException ignored){
}
}
final GPX gpx = GPX.builder().addTrack(track -> track.addSegment(segment.build())).build();
GPX.write(gpx, serializerFile.getAbsolutePath() + ".gpx");
Toast.makeText(this, R.string.toast_gpx_write, Toast.LENGTH_SHORT).show();
new File(serializerFile.getAbsolutePath() + ".tobeupload").createNewFile();;
}
private void startTrack(int time, boolean ele, boolean fine) {
TimerTask task = new TimerTask() {
public void run() {
Location location = getLocation(ele, fine);
if (location != null){
try {
if (location.getTime() != basetime){
basetime = location.getTime();
WayPoint point = WayPoint.builder().lat(location.getLatitude()).lon(location.getLongitude()).ele(location.getAltitude()).time(location.getTime()).build();
if (point != null){
oos.writeObject(point);
NotificationCompat.Builder timerBuilder = builder.setContentText(getString(R.string.tracktext) + sdf.format(location.getTime()));
Log.i("track", location.getLatitude() +","+ location.getLongitude() +","+ location.getAltitude());
notificationManager.notify(notificationId,timerBuilder.build());
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
};
timer.schedule(task, 0, time);
}
private Location getLocation(boolean ele, boolean fine) {
//get location here
}
}
jpx включает класс zonedDateTime, который работает в java8. Но он был перенесен в Java 6 его создателем Стивеном Колебурном, а также перенесен в раннюю версию android в виде библиотеки.
Библиотека находится здесь: JakeWharton / ThreeTenABP - Адаптация обратного порта JSR-310 для Android.
И как использовать: Как использовать ThreeTenABP в Android проекте - StackOverFlow