MyTracks 読み (9)
核心なソレを順に確認。
writeDocument メソドの先頭部分
void writeDocument() { Log.d(MyTracksConstants.TAG, "Started writing track."); writer.writeHeader();
writer って何かというと定義が以下。
private final TrackFormatWriter writer;
TrackFormatWriter は interface になっております。ええと TrackWriterFactory クラスに以下な記述があるんですが
public enum TrackFileFormat { GPX { @Override TrackFormatWriter newFormatWriter(Context context) { return new GpxTrackWriter(); } }, KML { @Override TrackFormatWriter newFormatWriter(Context context) { return new KmlTrackWriter(context); } }, CSV { @Override public TrackFormatWriter newFormatWriter(Context context) { return new CsvTrackWriter(); } };
この enum は一体何だ。何を override してるのかが不明 (わら
ええと、ExportAllTracks で Dialog 作っている模様。
private final DialogInterface.OnClickListener itemClick = new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { switch (which) { case GPX_OPTION_INDEX: format = TrackFileFormat.GPX; break; case KML_OPTION_INDEX: format = TrackFileFormat.KML; break; case CSV_OPTION_INDEX: format = TrackFileFormat.CSV; break; } } };
ここで format がリセットされて (デフォは GPX な模様)、TrackWriter#writeTrack() に渡されているのか。で、TrackWriterFactory#newWriter() で
public static TrackWriter newWriter(Context context, MyTracksProviderUtils providerUtils, Track track, TrackFileFormat format) { TrackFormatWriter writer = format.newFormatWriter(context); return new TrackWriter(context, providerUtils, track, writer); }
種別毎の TrackFormatWriter が戻されている模様。これも何かのパターンなのかな。具体的な処理が記述されているのが
- GpxTrackWriter
- KmlTrackWriter
- CsvTrackWriter
の三つなカンジ。ここに具体的な処理が記述されてないと困る。例えば KML 用のヘッダ出力は以下な形になっている模様。
@Override public void writeHeader() { if (pw != null) { pw.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); pw.print("<kml"); pw.print(" xmlns=\"http://earth.google.com/kml/2.0\""); pw.println(" xmlns:atom=\"http://www.w3.org/2005/Atom\">"); pw.println("<Document>"); pw.println("<atom:author><atom:name>My Tracks running on Android" + "</atom:name></atom:author>"); pw.println("<name>" + StringUtils.stringAsCData(track.getName()) + "</name>"); pw.println("<description>" + StringUtils.stringAsCData(track.getDescription()) + "</description>"); writeStyles(); } }
ざっくりベースな理解では微妙なので、
- Track クラス
- TrackBuffer クラス
- Location クラス
あと、MyTracksProviderUtils#getTrackPoints() というメソドも確認必要。あら? Location は android の Location なのか。
って
色々確認してたんですが、出力はローカルだった事が判明。実機の中身を見てみたらデータが保存されておりました。よく見てみたら MyTracksMap な画面の右下にボタンが配置されているのを発見。
タップして出力されるメニューには_Send to Google..._というソレが御座いました。ナチュラルにも程があるなぁ。
ざっくり確認した所
MyTracksMap クラスの
@Override public boolean onMenuItemSelected(int featureId, MenuItem item) { if (!super.onMenuItemSelected(featureId, item)) { if (selectedTrack != null) { MyTracks.getInstance().onActivityResult( MyTracksConstants.getActionFromMenuId(item.getItemId()), RESULT_OK, new Intent()); return true; } } return false; }
にて MyTracks の onMenuItemSelected の以下の部分か。
case MyTracksConstants.SEND_TO_GOOGLE_DIALOG: { shareRequested = false; showDialogSafely(DIALOG_SEND_TO_GOOGLE); break; } case MyTracksConstants.SEND_TO_GOOGLE: { if (results != null && resultCode == RESULT_OK) { final String mapid; final long trackId; if (results.hasExtra("mapid")) { mapid = results.getStringExtra("mapid"); } else { mapid = "new"; } if (results.hasExtra("trackid")) { trackId = results.getLongExtra("trackid", -1); } else { trackId = selectedTrackId; } final SendToMyMaps sender = new SendToMyMaps(this, mapid, auth, trackId, this/*progressIndicator*/); Runnable onCompletion = new Runnable() { public void run() { sendToMyMapsMessage = sender.getStatusMessage(); sendToMyMapsSuccess = sender.wasSuccess(); if (sendToMyMapsSuccess) { sendToMyMapsMapId = sender.getMapId(); // Update the map id for this track: try { Track track = providerUtils.getTrack(trackId); track.setMapId(sender.getMapId()); providerUtils.updateTrack(track); } catch (RuntimeException e) { // If that fails whatever reasons we'll just log an error, but // continue. Log.w(MyTracksConstants.TAG, "Updating map id failed.", e); } } if (sendToGoogleDialog.getSendToDocs()) { onActivityResult(MyTracksConstants.AUTHENTICATE_TO_DOCS, RESULT_OK, new Intent()); } else { dismissDialogSafely(DIALOG_PROGRESS); runOnUiThread(new Runnable() { public void run() { handleMapsFinish(); } }); } } }; sender.setOnCompletion(onCompletion); sender.run(); } else { dismissDialogSafely(DIALOG_PROGRESS); } break; }
ナチュラルも程々に、というソレですな。
しかし showDialogSafely というメソドが定義されてて
public void showDialogSafely(final int id) { runOnUiThread(new Runnable() { public void run() { try { showDialog(id); } catch (BadTokenException e) { Log.w(MyTracksConstants.TAG, "Could not display dialog with id " + id, e); } catch (IllegalStateException e) { Log.w(MyTracksConstants.TAG, "Could not display dialog with id " + id, e); } } }); }
showDialog というメソドを探してしまったんですが、これって android.app.Activity のメソドな模様。この showDialog というメソドが呼ばれる時に一度だけその id で onCreateDialog なメソドが呼び出される模様。
手続き的には以下なあたりな模様。
case DIALOG_SEND_TO_GOOGLE: sendToGoogleDialog = new SendToGoogleDialog(this); return sendToGoogleDialog; case DIALOG_SEND_TO_GOOGLE_RESULT: AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setIcon(android.R.drawable.ic_dialog_info); builder.setTitle("Title"); builder.setMessage("Message"); builder.setPositiveButton(getString(R.string.ok), null); builder.setNeutralButton(getString(R.string.share_map), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { shareLinkToMyMap(sendToMyMapsMapId); dialog.dismiss(); } }); sendToGoogleResultDialog = builder.create(); return sendToGoogleResultDialog;
今更こんなあたりを掘っているのって微妙杉だろ。(とほほほ
とりあえず
帰ってヤりますorz
むむ
SEND_TO_DOCS だったorz
case MyTracksConstants.SEND_TO_DOCS: { if (results != null && resultCode == RESULT_OK) { Log.d(MyTracksConstants.TAG, "Sending to Docs...."); setProgressValue(50); setProgressMessage(getString(R.string.progress_message_sending_docs)); final long trackId = results.getLongExtra("trackid", selectedTrackId); final SendToDocs sender = new SendToDocs(this, authMap.get("wise"), authMap.get("writely"), trackId); Runnable onCompletion = new Runnable() { public void run() { setProgressValue(100); dismissDialogSafely(DIALOG_PROGRESS); runOnUiThread(new Runnable() { public void run() { sendToDocsMessage = sender.getStatusMessage(); sendToDocsSuccess = sender.wasSuccess(); handleMapsFinish(); } }); } }; sender.setOnCompletion(onCompletion); sender.run(); } else { dismissDialogSafely(DIALOG_PROGRESS); } break; }
これ、順を追って見てかないと微妙だな。つーか何故にここまで onActivityResult とかでチェインしてるのかも微妙。