/*------------------------------------------------------------------------------
** Ident: Sogeti Smart Mobile Solutions
** Author: rene
** Copyright: (c) Apr 24, 2011 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.viewer;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.Dialog;
import android.app.ListActivity;
import android.app.SearchManager;
import android.content.*;
import android.content.DialogInterface.OnClickListener;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.*;
import android.widget.*;
import android.widget.CompoundButton.OnCheckedChangeListener;
import nl.sogeti.android.gpstracker.R;
import nl.sogeti.android.gpstracker.actions.DescribeTrack;
import nl.sogeti.android.gpstracker.actions.NameTrack;
import nl.sogeti.android.gpstracker.actions.Statistics;
import nl.sogeti.android.gpstracker.actions.tasks.GpxParser;
import nl.sogeti.android.gpstracker.actions.tasks.StationsJSONParser;
import nl.sogeti.android.gpstracker.actions.tasks.StationsXMLParser;
import nl.sogeti.android.gpstracker.actions.utils.ProgressListener;
import nl.sogeti.android.gpstracker.adapter.BreadcrumbsAdapter;
import nl.sogeti.android.gpstracker.adapter.BreadcrumbsTracks;
import nl.sogeti.android.gpstracker.adapter.SectionedListAdapter;
import nl.sogeti.android.gpstracker.db.DatabaseHelper;
import nl.sogeti.android.gpstracker.db.GPStracking;
import nl.sogeti.android.gpstracker.db.GPStracking.Tracks;
import nl.sogeti.android.gpstracker.util.Constants;
import nl.sogeti.android.gpstracker.util.Pair;
/**
* Show a list view of all tracks, also doubles for showing search results
*
* @version $Id: TrackList.java 1144 2011-10-30 11:19:53Z rcgroot $
* @author rene (c) Jan 11, 2009, Sogeti B.V.
*/
public class TrackList extends ListActivity implements ProgressListener
{
private static final String TAG = "OGT.TrackList";
private static final int MENU_DETELE = Menu.FIRST + 0;
private static final int MENU_SHARE = Menu.FIRST + 1;
private static final int MENU_RENAME = Menu.FIRST + 2;
private static final int MENU_STATS = Menu.FIRST + 3;
private static final int MENU_SEARCH = Menu.FIRST + 4;
private static final int MENU_VACUUM = Menu.FIRST + 5;
private static final int MENU_PICKER = Menu.FIRST + 6;
private static final int MENU_BREADCRUMBS = Menu.FIRST + 7;
private static final int MENU_BUILD_STATIONS_TABLE = Menu.FIRST + 8;
public static final int DIALOG_FILENAME = Menu.FIRST + 22;
private static final int DIALOG_RENAME = Menu.FIRST + 23;
private static final int DIALOG_DELETE = Menu.FIRST + 24;
private static final int DIALOG_VACUUM = Menu.FIRST + 25;
private static final int DIALOG_IMPORT = Menu.FIRST + 26;
private static final int DIALOG_INSTALL = Menu.FIRST + 27;
protected static final int DIALOG_ERROR = Menu.FIRST + 28;
private static final int PICKER_OI = Menu.FIRST + 29;
private static final int DESCRIBE = Menu.FIRST + 30;
private BreadcrumbsAdapter mBreadcrumbAdapter;
private Uri mDialogUri;
private String mDialogCurrentName = "";
private String mErrorDialogMessage;
private Exception mErrorDialogException;
private Runnable mImportAction;
private OnClickListener mDeleteOnClickListener = new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int which)
{
getContentResolver().delete(mDialogUri, null, null);
}
};
private OnClickListener mVacuumOnClickListener = new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int which)
{
DatabaseHelper helper = new DatabaseHelper(TrackList.this);
helper.vacuum();
}
};
private OnClickListener mImportOnClickListener = new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int which)
{
mImportAction.run();
}
};
private final DialogInterface.OnClickListener mOiPickerDialogListener = new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int which)
{
Uri oiDownload = Uri.parse("market://details?id=org.openintents.filemanager");
Intent oiAboutIntent = new Intent(Intent.ACTION_VIEW, oiDownload);
try
{
startActivity(oiAboutIntent);
}
catch (ActivityNotFoundException e)
{
oiDownload = Uri.parse("http://openintents.googlecode.com/files/FileManager-1.1.3.apk");
oiAboutIntent = new Intent(Intent.ACTION_VIEW, oiDownload);
startActivity(oiAboutIntent);
}
}
};
private String mImportTrackName;
private String mErrorTask;
/**
* Progress listener for the background tasks uploading to gobreadcrumbs
*/
private ProgressListener mExportListener;
private int mPausePosition;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
getWindow().requestFeature(Window.FEATURE_PROGRESS);
this.setContentView(R.layout.tracklist);
displayIntent(getIntent());
ListView listView = getListView();
listView.setItemsCanFocus(true);
// Add the context menu (the long press thing)
registerForContextMenu(listView);
if( savedInstanceState != null )
{
getListView().setSelection(savedInstanceState.getInt("POSITION"));
}
}
@Override
protected void onResume()
{
if( mPausePosition != 0 )
{
getListView().setSelection(mPausePosition);
}
super.onResume();
}
@Override
protected void onPause()
{
mPausePosition = getListView().getFirstVisiblePosition();
super.onPause();
}
@Override
protected void onDestroy()
{
if (mBreadcrumbAdapter != null && isFinishing())
{
mBreadcrumbAdapter.shutdown();
}
super.onDestroy();
}
@Override
public Object onRetainNonConfigurationInstance()
{
return mBreadcrumbAdapter;
}
@Override
public void onNewIntent(Intent newIntent)
{
displayIntent(newIntent);
}
/*
* (non-Javadoc)
* @see android.app.ListActivity#onRestoreInstanceState(android.os.Bundle)
*/
@Override
protected void onRestoreInstanceState(Bundle state)
{
super.onRestoreInstanceState(state);
mDialogUri = state.getParcelable("URI");
mDialogCurrentName = state.getString("NAME");
mDialogCurrentName = mDialogCurrentName != null ? mDialogCurrentName : "";
getListView().setSelection(state.getInt("POSITION"));
}
/*
* (non-Javadoc)
* @see android.app.Activity#onSaveInstanceState(android.os.Bundle)
*/
@Override
protected void onSaveInstanceState(Bundle outState)
{
super.onSaveInstanceState(outState);
outState.putParcelable("URI", mDialogUri);
outState.putString("NAME", mDialogCurrentName);
outState.putInt("POSITION",getListView().getFirstVisiblePosition());
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
boolean result = super.onCreateOptionsMenu(menu);
menu.add(ContextMenu.NONE, MENU_SEARCH, ContextMenu.NONE, android.R.string.search_go).setIcon(android.R.drawable.ic_search_category_default)
.setAlphabeticShortcut(SearchManager.MENU_KEY);
menu.add(ContextMenu.NONE, MENU_VACUUM, ContextMenu.NONE, R.string.menu_vacuum).setIcon(android.R.drawable.ic_menu_crop);
menu.add(ContextMenu.NONE, MENU_PICKER, ContextMenu.NONE, R.string.menu_picker).setIcon(android.R.drawable.ic_menu_add);
menu.add(ContextMenu.NONE, MENU_BUILD_STATIONS_TABLE, ContextMenu.NONE, "Build stations table").setIcon(android.R.drawable.ic_menu_save);
menu.add(ContextMenu.NONE, MENU_BREADCRUMBS, ContextMenu.NONE, R.string.dialog_breadcrumbsconnect).setIcon(android.R.drawable.ic_menu_revert);
return result;
}
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
boolean handled = false;
switch (item.getItemId())
{
case MENU_SEARCH:
onSearchRequested();
handled = true;
break;
case MENU_VACUUM:
showDialog(DIALOG_VACUUM);
break;
case MENU_BUILD_STATIONS_TABLE:
//Somehow the following line works, thks open source gpstracker code !
int provider = new Integer(PreferenceManager.getDefaultSharedPreferences(this).getString(Constants.BIKESYSTEM, "" + Constants.VELOTOULOUSE)).intValue();
switch (provider)
{
case Constants.VELOTOULOUSE:
//Toulouse over the public web
//Original data can be found here
//https://abo-toulouse.cyclocity.fr/service/carto I reformated it with a Google refine project
//you can find it here http://dl.dropbox.com/u/23857381/ToulouseStationsStaticData-xml.google-refine.tar.gz
//I did it as an exercise to understand JSON and XML formats, maybe I could just export it directly in JSON
//too now I have written the code for Velov'
//The citybik.es python lib uses that library to directly parse the original data
//http://www.crummy.com/software/BeautifulSoup/
//from https://github.com/eskerda/PyBikes/blob/master/lib/BeautifulSoup.py
//new StationsXMLParser(TrackList.this, TrackList.this).execute("http://f8full.is-a-geek.org:666/ToulouseStationsStaticData-xml.xml");
new StationsXMLParser(TrackList.this, TrackList.this).execute("http://dl.dropbox.com/u/23857381/ToulouseStationsStaticData-xml.xml");
break;
case Constants.VELOV:
//Lyon, over the public web, URLs are constructed in parser
new StationsJSONParser(TrackList.this, TrackList.this).execute();
break;
default:
Log.e(TAG, "Fault in value " + provider + " as BikeSystem.");
break;
}
//Bixi over my private network
//new StationsXMLParser(TrackList.this, TrackList.this).execute("http://192.168.1.18:666/01_10_2010__16_55_01.xml");
//Bixi over the public web -- to replace with actual feed URL when season will be started
//new StationsXMLParser(TrackList.this, TrackList.this).execute("http://f8full.is-a-geek.org:666/01_10_2010__16_55_01.xml");
//Toronto over the public web
//new StationsXMLParser(TrackList.this, TrackList.this).execute("https://toronto.bixi.com/data/bikeStations.xml");
//Toulouse over the public web
//new StationsXMLParser(TrackList.this, TrackList.this).execute("http://f8full.is-a-geek.org:666/ToulouseStationsStaticData-xml.xml");
//Lyon, over the public web, URLs are constructed in parser
//new StationsJSONParser(TrackList.this, TrackList.this).execute();
break;
case MENU_PICKER:
try
{
Intent intent = new Intent("org.openintents.action.PICK_FILE");
intent.putExtra("org.openintents.extra.TITLE", getString(R.string.dialog_import_picker));
intent.putExtra("org.openintents.extra.BUTTON_TEXT", getString(R.string.menu_picker));
startActivityForResult(intent, PICKER_OI);
}
catch (ActivityNotFoundException e)
{
showDialog(DIALOG_INSTALL);
}
break;
case MENU_BREADCRUMBS:
mBreadcrumbAdapter.removeAuthentication();
mBreadcrumbAdapter.getBreadcrumbsTracks().clearAllCache(this);
mBreadcrumbAdapter.requestBreadcrumbsOauthToken(this);
break;
default:
handled = super.onOptionsItemSelected(item);
}
return handled;
}
@Override
protected void onListItemClick(ListView listView, View view, int position, long id)
{
super.onListItemClick(listView, view, position, id);
Object item = listView.getItemAtPosition(position);
if (item instanceof String)
{
if (Constants.BREADCRUMBS_CONNECT.equals(item))
{
mBreadcrumbAdapter.requestBreadcrumbsOauthToken(this);
}
}
else if (item instanceof Pair< ? , ? >)
{
@SuppressWarnings("unchecked")
final Pair<Integer, Integer> track = (Pair<Integer, Integer>) item;
if (track.first == Constants.BREADCRUMBS_TRACK_ITEM_VIEW_TYPE)
{
TextView tv = (TextView) view.findViewById(R.id.listitem_name);
mImportTrackName = tv.getText().toString();
mImportAction = new Runnable()
{
public void run()
{
mBreadcrumbAdapter.startDownloadTask(TrackList.this, TrackList.this, track);
}
};
showDialog(DIALOG_IMPORT);
}
}
else
{
Intent intent = new Intent();
Uri trackUri = ContentUris.withAppendedId(Tracks.CONTENT_URI, id);
intent.setData(trackUri);
ComponentName caller = this.getCallingActivity();
if (caller != null)
{
setResult(RESULT_OK, intent);
finish();
}
else
{
intent.setClass(this, LoggerMap.class);
startActivity(intent);
}
}
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo)
{
if (menuInfo instanceof AdapterView.AdapterContextMenuInfo)
{
AdapterView.AdapterContextMenuInfo itemInfo = (AdapterView.AdapterContextMenuInfo) menuInfo;
TextView textView = (TextView) itemInfo.targetView.findViewById(R.id.listitem_name);
if (textView != null)
{
menu.setHeaderTitle(textView.getText());
}
Object listItem = getListAdapter().getItem(itemInfo.position);
if( listItem instanceof Cursor)
{
menu.add(0, MENU_STATS, 0, R.string.menu_statistics);
menu.add(0, MENU_SHARE, 0, R.string.menu_shareTrack);
menu.add(0, MENU_RENAME, 0, R.string.menu_renameTrack);
menu.add(0, MENU_DETELE, 0, R.string.menu_deleteTrack);
}
}
}
@Override
public boolean onContextItemSelected(MenuItem item)
{
boolean handled = false;
AdapterView.AdapterContextMenuInfo info;
try
{
info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
}
catch (ClassCastException e)
{
Log.e(TAG, "Bad menuInfo", e);
return handled;
}
Object listItem = getListAdapter().getItem(info.position);
if( listItem instanceof Cursor)
{
Cursor cursor = (Cursor) listItem;
mDialogUri = ContentUris.withAppendedId(Tracks.CONTENT_URI, cursor.getLong(0));
mDialogCurrentName = cursor.getString(1);
mDialogCurrentName = mDialogCurrentName != null ? mDialogCurrentName : "";
switch (item.getItemId())
{
case MENU_DETELE:
{
showDialog(DIALOG_DELETE);
handled = true;
break;
}
case MENU_SHARE:
{
Intent actionIntent = new Intent(Intent.ACTION_RUN);
actionIntent.setDataAndType(mDialogUri, Tracks.CONTENT_ITEM_TYPE);
actionIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(Intent.createChooser(actionIntent, getString(R.string.share_track)));
handled = true;
break;
}
case MENU_RENAME:
{
// Start a naming of the track
//Note : this is more of a describe thing than naming now, but a describe activity already exists
//Maybe use detailTrack or something
Intent namingIntent = new Intent( this, NameTrack.class );
namingIntent.setData( mDialogUri ); //Contains track URI, in fact
startActivity( namingIntent );
handled = true;
break;
}
case MENU_STATS:
{
Intent actionIntent = new Intent(this, Statistics.class);
actionIntent.setData(mDialogUri);
startActivity(actionIntent);
handled = true;
break;
}
default:
handled = super.onContextItemSelected(item);
break;
}
}
return handled;
}
/*
* (non-Javadoc)
* @see android.app.Activity#onCreateDialog(int)
*/
@Override
protected Dialog onCreateDialog(int id)
{
Dialog dialog = null;
Builder builder = null;
switch (id)
{
case DIALOG_DELETE:
builder = new AlertDialog.Builder(TrackList.this).setTitle(R.string.dialog_delete_title).setIcon(android.R.drawable.ic_dialog_alert)
.setNegativeButton(android.R.string.cancel, null).setPositiveButton(android.R.string.ok, mDeleteOnClickListener);
dialog = builder.create();
String messageFormat = this.getResources().getString(R.string.dialog_delete_message);
String message = String.format(messageFormat, "");
((AlertDialog) dialog).setMessage(message);
return dialog;
case DIALOG_VACUUM:
builder = new AlertDialog.Builder(TrackList.this).setTitle(R.string.dialog_vacuum_title).setMessage(R.string.dialog_vacuum_message)
.setIcon(android.R.drawable.ic_dialog_alert).setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(android.R.string.ok, mVacuumOnClickListener);
dialog = builder.create();
return dialog;
case DIALOG_IMPORT:
builder = new AlertDialog.Builder(TrackList.this).setTitle(R.string.dialog_import_title)
.setMessage(getString(R.string.dialog_import_message, mImportTrackName)).setIcon(android.R.drawable.ic_dialog_alert)
.setNegativeButton(android.R.string.cancel, null).setPositiveButton(android.R.string.ok, mImportOnClickListener);
dialog = builder.create();
return dialog;
case DIALOG_INSTALL:
builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.dialog_nooipicker).setMessage(R.string.dialog_nooipicker_message).setIcon(android.R.drawable.ic_dialog_alert)
.setPositiveButton(R.string.btn_install, mOiPickerDialogListener).setNegativeButton(R.string.btn_cancel, null);
dialog = builder.create();
return dialog;
case DIALOG_ERROR:
builder = new AlertDialog.Builder(this);
builder.setIcon(android.R.drawable.ic_dialog_alert).setTitle(android.R.string.dialog_alert_title).setMessage(mErrorDialogMessage)
.setNeutralButton(android.R.string.cancel, null);
dialog = builder.create();
return dialog;
default:
return super.onCreateDialog(id);
}
}
/*
* (non-Javadoc)
* @see android.app.Activity#onPrepareDialog(int, android.app.Dialog)
*/
@Override
protected void onPrepareDialog(int id, Dialog dialog)
{
super.onPrepareDialog(id, dialog);
AlertDialog alert;
String message;
switch (id)
{
case DIALOG_DELETE:
alert = (AlertDialog) dialog;
String messageFormat = this.getResources().getString(R.string.dialog_delete_message);
message = String.format(messageFormat, mDialogCurrentName);
alert.setMessage(message);
break;
case DIALOG_ERROR:
alert = (AlertDialog) dialog;
message = "Failed task:\n" + mErrorTask;
message += "\n\n";
message += "Reason:\n" + mErrorDialogMessage;
if (mErrorDialogException != null)
{
message += " (" + mErrorDialogException.getMessage() + ") ";
}
alert.setMessage(message);
break;
case DIALOG_IMPORT:
alert = (AlertDialog) dialog;
alert.setMessage(getString(R.string.dialog_import_message, mImportTrackName));
break;
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
if (resultCode != RESULT_CANCELED)
{
switch (requestCode)
{
case PICKER_OI:
new GpxParser(TrackList.this, TrackList.this).execute(data.getData());
break;
case DESCRIBE:
Uri trackUri = data.getData();
String name;
if (data.getExtras() != null && data.getExtras().containsKey(Constants.NAME))
{
name = data.getExtras().getString(Constants.NAME);
}
else
{
name = "shareToGobreadcrumbs";
}
mBreadcrumbAdapter.startUploadTask(TrackList.this, mExportListener, trackUri, name);
break;
default:
super.onActivityResult(requestCode, resultCode, data);
break;
}
}
else
{
if (requestCode == DESCRIBE)
{
mBreadcrumbAdapter.notifyDataSetChanged();
}
}
}
private void displayIntent(Intent intent)
{
final String queryAction = intent.getAction();
final String orderby = Tracks.CREATION_TIME + " DESC";
Cursor tracksCursor = null;
if (Intent.ACTION_SEARCH.equals(queryAction))
{
// Got to SEARCH a query for tracks, make a list
tracksCursor = doSearchWithIntent(intent);
}
else if (Intent.ACTION_VIEW.equals(queryAction))
{
final Uri uri = intent.getData();
if ("content".equals(uri.getScheme()) && GPStracking.AUTHORITY.equals(uri.getAuthority()))
{
// Got to VIEW a single track, instead hand it of to the LoggerMap
Intent notificationIntent = new Intent(this, LoggerMap.class);
notificationIntent.setData(uri);
startActivity(notificationIntent);
finish();
}
else if (uri.getScheme().equals("file") || uri.getScheme().equals("content"))
{
mImportTrackName = uri.getLastPathSegment();
// Got to VIEW a GPX filename
mImportAction = new Runnable()
{
public void run()
{
new GpxParser(TrackList.this, TrackList.this).execute(uri);
}
};
showDialog(DIALOG_IMPORT);
tracksCursor = managedQuery(Tracks.CONTENT_URI, new String[] { Tracks._ID, Tracks.NAME, Tracks.CREATION_TIME }, null, null, orderby);
}
else
{
Log.e(TAG, "Unable to VIEW " + uri);
}
}
else
{
// Got to nothing, make a list of everything
tracksCursor = managedQuery(Tracks.CONTENT_URI, new String[] { Tracks._ID, Tracks.NAME, Tracks.CREATION_TIME }, null, null, orderby);
}
displayCursor(tracksCursor);
}
private void displayCursor(Cursor tracksCursor)
{
SectionedListAdapter sectionedAdapter = new SectionedListAdapter(this);
String[] fromColumns = new String[] { Tracks.NAME, Tracks.CREATION_TIME, Tracks._ID };
int[] toItems = new int[] { R.id.listitem_name, R.id.listitem_from, R.id.bcSyncedCheckBox };
SimpleCursorAdapter trackAdapter = new SimpleCursorAdapter(this, R.layout.trackitem, tracksCursor, fromColumns, toItems);
sectionedAdapter.addSection("Local", trackAdapter);
mBreadcrumbAdapter = (BreadcrumbsAdapter) getLastNonConfigurationInstance();
if (mBreadcrumbAdapter == null)
{
mBreadcrumbAdapter = new BreadcrumbsAdapter(this, this);
mBreadcrumbAdapter.connectionSetup();
}
sectionedAdapter.addSection("GoBreadcrumbs", mBreadcrumbAdapter);
// Enrich the track adapter with Breadcrumbs adapter data
trackAdapter.setViewBinder(new SimpleCursorAdapter.ViewBinder()
{
public boolean setViewValue(View view, final Cursor cursor, int columnIndex)
{
if (columnIndex == 0)
{
final long trackId = cursor.getLong(0);
final String trackName = cursor.getString(1);
// Show the check if Breadcrumbs is online
final CheckBox checkbox = (CheckBox) view;
final ProgressBar progressbar = (ProgressBar) ((View)view.getParent()).findViewById(R.id.bcExportProgress);
if (mBreadcrumbAdapter.isOnline())
{
checkbox.setVisibility(View.VISIBLE);
// Disable the checkbox if marked online
BreadcrumbsTracks tracks = mBreadcrumbAdapter.getBreadcrumbsTracks();
boolean isOnline = tracks.isLocalTrackSynced(trackId);
checkbox.setEnabled(!isOnline);
// Check the checkbox if determined synced
boolean isSynced = tracks.isLocalTrackSynced(trackId);
checkbox.setOnCheckedChangeListener(null);
checkbox.setChecked(isSynced);
checkbox.setOnCheckedChangeListener(new OnCheckedChangeListener()
{
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
{
if (isChecked)
{
// Start a description of the track
Intent namingIntent = new Intent(TrackList.this, DescribeTrack.class);
namingIntent.setData(ContentUris.withAppendedId(Tracks.CONTENT_URI, trackId));
namingIntent.putExtra(Constants.NAME, trackName);
mExportListener = new ProgressListener()
{
public void setIndeterminate(boolean indeterminate)
{
progressbar.setIndeterminate(indeterminate);
}
public void started()
{
checkbox.setVisibility(View.INVISIBLE);
progressbar.setVisibility(View.VISIBLE);
}
public void finished(Uri result)
{
checkbox.setVisibility(View.VISIBLE);
progressbar.setVisibility(View.INVISIBLE);
progressbar.setIndeterminate(false);
}
public void setProgress(int value)
{
progressbar.setProgress(value);
}
public void showError(String task, String errorMessage, Exception exception)
{
TrackList.this.showError(task, errorMessage, exception);
}
};
startActivityForResult(namingIntent, DESCRIBE);
}
}
});
}
else
{
checkbox.setVisibility(View.INVISIBLE);
checkbox.setOnCheckedChangeListener(null);
}
return true;
}
return false;
}
});
setListAdapter(sectionedAdapter);
}
private Cursor doSearchWithIntent(final Intent queryIntent)
{
final String queryString = queryIntent.getStringExtra(SearchManager.QUERY);
return managedQuery(Tracks.CONTENT_URI, new String[] { Tracks._ID, Tracks.NAME, Tracks.CREATION_TIME }, "name LIKE ?", new String[] { "%"
+ queryString + "%" }, null);
}
/*******************************************************************/
/** ProgressListener interface and UI actions (non-Javadoc) **/
/*******************************************************************/
public void setIndeterminate(boolean indeterminate)
{
setProgressBarIndeterminate(indeterminate);
}
public void started()
{
setProgressBarVisibility(true);
setProgress(Window.PROGRESS_START);
}
public void finished(Uri result)
{
setProgressBarVisibility(false);
setProgressBarIndeterminate(false);
}
public void showError(String task, String errorDialogMessage, Exception errorDialogException)
{
mErrorTask = task;
mErrorDialogMessage = errorDialogMessage;
mErrorDialogException = errorDialogException;
Log.e(TAG, errorDialogMessage, errorDialogException);
if (!isFinishing())
{
showDialog(DIALOG_ERROR);
}
setProgressBarVisibility(false);
setProgressBarIndeterminate(false);
}
}