/*------------------------------------------------------------------------------ ** Ident: Innovation en Inspiration > Google Android ** Author: rene ** Copyright: (c) Jan 22, 2009 Sogeti Nederland B.V. All Rights Reserved. **------------------------------------------------------------------------------ ** Sogeti Nederland B.V. | No part of this file may be reproduced ** Distributed Software Engineering | or transmitted in any form or by any ** Lange Dreef 17 | means, electronic or mechanical, for the ** 4131 NJ Vianen | purpose, without the express written ** The Netherlands | permission of the copyright holder. *------------------------------------------------------------------------------ * * This file is part of OpenGPSTracker. * * OpenGPSTracker is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * OpenGPSTracker is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenGPSTracker. If not, see <http://www.gnu.org/licenses/>. * */ package nl.sogeti.android.gpstracker.actions; import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import nl.sogeti.android.gpstracker.R; import nl.sogeti.android.gpstracker.db.GPStracking.Segments; import nl.sogeti.android.gpstracker.db.GPStracking.Tracks; import nl.sogeti.android.gpstracker.db.GPStracking.Waypoints; import nl.sogeti.android.gpstracker.viewer.LoggerMap; import org.xmlpull.v1.XmlSerializer; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.ContentUris; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.os.Looper; import android.util.Log; import android.util.Xml; import android.widget.RemoteViews; import android.widget.Toast; /** * ???? * * @version $Id: ExportGPX.java 100 2009-10-19 19:49:02Z rcgroot@gmail.com $ * @author rene (c) Mar 22, 2009, Sogeti B.V. */ public class ExportGPX extends BroadcastReceiver { private static final int PROGRESS_STEPS = 10; private static final String NS_SCHEMA = "http://www.w3.org/2001/XMLSchema-instance"; private static final String NS_GPX_11 = "http://www.topografix.com/GPX/1/1"; public static final String FILENAME = null; private static final String DATETIME = "yyyy-MM-dd'T'HH:mm:ss'Z'"; protected static final String TAG = "ExportGPX"; private RemoteViews mContentView; private int barProgress = 0; private int mProgress = 0; private int mGoal = 0; private Notification mNotification; private NotificationManager mNotificationManager; @Override public void onReceive( final Context context, final Intent intent ) { // Log.d( TAG, "Receive intent "+intent ); new Thread(new Runnable() { public void run() { Looper.prepare(); String fileName = "UntitledTrack.gpx"; Uri trackUri = intent.getData(); Cursor trackCursor = null ; ContentResolver resolver = context.getContentResolver(); try { trackCursor = resolver.query ( trackUri , new String[] { Tracks.NAME } , null , null , null ); if( trackCursor.moveToLast() ) { fileName = trackCursor.getString( 0 )+".gpx"; } } finally { if( trackCursor != null ) { trackCursor.close(); } } String filePath = "/sdcard/"+fileName; String ns = Context.NOTIFICATION_SERVICE; mNotificationManager = (NotificationManager) context.getSystemService(ns); int icon = android.R.drawable.ic_menu_save; CharSequence tickerText = "Saving:\""+fileName+"\""; mNotification = new Notification(); PendingIntent contentIntent = PendingIntent.getActivity(context, 0, new Intent(context, LoggerMap.class).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK), PendingIntent.FLAG_UPDATE_CURRENT); mNotification.contentIntent = contentIntent; mNotification.tickerText = tickerText; mNotification.icon = icon; mNotification.flags |= Notification.FLAG_ONGOING_EVENT; mContentView = new RemoteViews(context.getPackageName(), R.layout.savenotificationprogress ); mContentView.setImageViewResource( R.id.icon, icon); mContentView.setTextViewText( R.id.progresstext, tickerText ); mNotification.contentView = mContentView; updateNotification(); try { XmlSerializer serializer = Xml.newSerializer(); BufferedOutputStream buf = new BufferedOutputStream(new FileOutputStream(filePath), 8192); serializer.setOutput( buf, "UTF-8" ); serializer.startDocument( "UTF-8", true ); serializer.setPrefix( "xsi", NS_SCHEMA ); serializer.setPrefix( "gpx", NS_GPX_11 ); serializer.startTag( "", "gpx" ); serializer.attribute( null, "version", "1.1" ); serializer.attribute( null, "creator", "nl.sogeti.android.gpstracker" ); serializer.attribute( NS_SCHEMA, "schemaLocation", NS_GPX_11+" http://www.topografix.com/gpx/1/1/gpx.xsd" ); serializer.attribute( null, "xmlns", NS_GPX_11 ); // Big header of the track String name = serializeTrack( context, serializer, trackUri ); serializer.text( "\n" ); serializer.startTag( "", "trk" ); serializer.text( "\n" ); serializer.startTag( "", "name" ); serializer.text( name ); serializer.endTag( "", "name" ); // The list of segments in the track serializeSegments( context, serializer, Uri.withAppendedPath( trackUri, "segments" ) ); serializer.text( "\n" ); serializer.endTag( "", "trk" ); serializer.text( "\n" ); serializer.endTag( "", "gpx" ); serializer.endDocument(); CharSequence text = "Stored on SD-Card the route: "+fileName; Toast toast = Toast.makeText( context.getApplicationContext(), text, Toast.LENGTH_SHORT ); toast.show(); } catch (IllegalArgumentException e) { Log.e( TAG, "Unable to save "+e ); CharSequence text = "Unable to save the route: "+fileName+" reason: Incorrect filename"; Toast toast = Toast.makeText( context.getApplicationContext(), text, Toast.LENGTH_LONG ); toast.show(); } catch (IllegalStateException e) { Log.e( TAG, "Unable to save "+e ); CharSequence text = "Unable to save the route: "+fileName+" reason: Error building XML"; Toast toast = Toast.makeText( context.getApplicationContext(), text, Toast.LENGTH_LONG ); toast.show(); } catch (IOException e) { Log.e( TAG, "Unable to save "+e ); CharSequence text = "Unable to save the route: "+fileName+" reason: Error writing to SD card"; Toast toast = Toast.makeText( context.getApplicationContext(), text, Toast.LENGTH_LONG ); toast.show(); } finally { mNotificationManager.cancel( R.layout.savenotificationprogress ); Looper.loop(); } } }).start(); } private String serializeTrack(Context context, XmlSerializer serializer, Uri trackUri ) throws IOException { ContentResolver resolver = context.getContentResolver(); Cursor trackCursor = null; String name = null; try { trackCursor = resolver.query( trackUri, new String[] { Tracks._ID, Tracks.NAME, Tracks.CREATION_TIME }, null, null, null); if( trackCursor.moveToFirst() ) { name = trackCursor.getString( 1 ) ; serializer.startTag( "", "metadata" ); serializer.startTag( "", "time" ); Date time = new Date( trackCursor.getLong( 2 ) ); DateFormat formater = new SimpleDateFormat(DATETIME); serializer.text( formater.format( time ) ); serializer.endTag( "", "time" ); serializer.endTag( "", "metadata" ); } } finally { if( trackCursor != null ) { trackCursor.close(); } } return name; } private void serializeSegments( Context context, XmlSerializer serializer, Uri segments ) throws IOException { Cursor segmentCursor = null; ContentResolver resolver = context.getContentResolver(); try { segmentCursor = resolver.query( segments, new String[] { Segments._ID }, null, null, null); if( segmentCursor.moveToFirst() ) { updateNotification(); do { Uri waypoints = Uri.withAppendedPath( segments, "/"+segmentCursor.getLong( 0 )+"/waypoints" ); serializer.text( "\n" ); serializer.startTag( "", "trkseg" ); serializeWaypoints( context, serializer, waypoints ); serializer.text( "\n" ); serializer.endTag( "", "trkseg" ); } while( segmentCursor.moveToNext() ); } } finally { if( segmentCursor != null ) { segmentCursor.close(); } } } private void serializeWaypoints( Context context, XmlSerializer serializer, Uri waypoints ) throws IOException { Cursor waypointsCursor = null; ContentResolver resolver = context.getContentResolver(); try { waypointsCursor = resolver.query( waypoints, new String[] { Waypoints.LONGITUDE, Waypoints.LATITUDE, Waypoints.TIME }, null, null, null); if( waypointsCursor.moveToFirst() ) { mGoal += waypointsCursor.getCount(); do { mProgress++; updateNotification(); serializer.text( "\n" ); serializer.startTag( "", "trkpt" ); serializer.attribute( null, "lat", waypointsCursor.getString( 1 ) ); serializer.attribute( null, "lon", waypointsCursor.getString( 0 ) ); serializer.text( "\n" ); serializer.startTag( "", "time" ); Date time = new Date( waypointsCursor.getLong( 2 ) ); DateFormat formater = new SimpleDateFormat(DATETIME); serializer.text( formater.format( time ) ); serializer.endTag( "", "time" ); serializer.text( "\n" ); serializer.startTag( "", "name" ); serializer.text( "point_"+waypointsCursor.getPosition() ); serializer.endTag( "", "name" ); serializer.text( "\n" ); serializer.endTag( "", "trkpt" ); } while( waypointsCursor.moveToNext() ); } } finally { if( waypointsCursor != null ) { waypointsCursor.close(); } } } private void updateNotification() { if( mProgress > 0 && mProgress < mGoal) { if( (mProgress*PROGRESS_STEPS)/mGoal != barProgress ) { barProgress = (mProgress*PROGRESS_STEPS)/mGoal ; mContentView.setProgressBar( R.id.progress, mGoal, mProgress, false ); mNotificationManager.notify( R.layout.savenotificationprogress, mNotification ); } } else if( mProgress == 0 ) { mContentView.setProgressBar( R.id.progress, mGoal, mProgress, true ); mNotificationManager.notify( R.layout.savenotificationprogress, mNotification ); } else if( mProgress >= mGoal ) { mContentView.setProgressBar( R.id.progress, mGoal, mProgress, false ); mNotificationManager.notify( R.layout.savenotificationprogress, mNotification ); } } }