package com.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import com.limegroup.gnutella.Downloader;
import com.limegroup.gnutella.R;
import com.limegroup.gnutella.downloader.AlreadyDownloadingException;
import com.util.DownloadInfo;
import com.util.DownloadObserver;
import com.util.DownloadService;
import com.util.P2pDownloadInfo;
import com.util.Utils;
import android.app.ListActivity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.provider.MediaStore;
import android.text.TextUtils;
import android.util.Log;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener;
public class DownloadActivity extends ListActivity {
protected ArrayList<DownloadInfo> mData;
protected DownloadService mDownloadService;
protected static final int MENU_CLEAR = Menu.FIRST;
protected static final int MENU_STOP = Menu.FIRST + 1;
protected static final int MENU_RESUME = Menu.FIRST + 2;
protected static final int MENU_DELETE = Menu.FIRST + 3;
protected static final int MENU_PAUSE = Menu.FIRST + 4;
protected static final int MENU_RETRY = Menu.FIRST + 5;
protected DownloadListAdapter mAdapter;
private Handler mHandler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.download);
bindService(new Intent(this, DownloadService.class),
mConnection, Context.BIND_AUTO_CREATE);
Button clearFinishedButton = (Button)findViewById(R.id.clear_finished_button);
clearFinishedButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (mDownloadService != null) {
mDownloadService.clearFinished();
}
}
});
Button hideButton = (Button)findViewById(R.id.hide_button);
hideButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
getListView().setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v,
int position, long id) {
if (mData == null || position >= mData.size())
return;
DownloadInfo d = mData.get(position);
if (d == null) {
Utils.D("No bound download info.");
return;
}
// Default action.
//int state = d.getState();
//if (state == Downloader.COMPLETE) {
// playDownloadedMusic(d);
//}
if (d.showToastForLongPress()) {
Toast.makeText(DownloadActivity.this,
getString(R.string.music_option_prompt), Toast.LENGTH_LONG).show();
}
}
});
getListView().setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() {
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
if (mData == null)
return;
if (!(menuInfo instanceof AdapterContextMenuInfo))
return;
int position = ((AdapterContextMenuInfo) menuInfo).position;
if (position >= mData.size())
return;
DownloadInfo d = mData.get(position);
if (d == null) {
Utils.D("No bound download info.");
return;
}
int state = d.getState();
if (state == Downloader.COMPLETE) {
//menu.add(0, MENU_PLAY, 0, R.string.play);
menu.add(0, MENU_CLEAR, 0, R.string.clear);
} else if (state == Downloader.CORRUPT_FILE ||
state == Downloader.ABORTED ||
state == Downloader.GAVE_UP ||
state == Downloader.RECOVERY_FAILED) {
menu.add(0, MENU_RETRY, 0, R.string.retry);
menu.add(0, MENU_DELETE, 0, R.string.delete);
} else if (state == Downloader.DOWNLOADING ||
state == Downloader.CONNECTING ||
state == Downloader.REMOTE_QUEUED ||
state == Downloader.SAVING ||
state == Downloader.IDENTIFY_CORRUPTION ||
state == Downloader.WAITING_FOR_RESULTS ||
state == Downloader.WAITING_FOR_RETRY ||
state == Downloader.WAITING_FOR_CONNECTIONS ||
state == Downloader.ITERATIVE_GUESSING) {
if (!d.isScheduled()) {
menu.add(0, MENU_RETRY, 0, R.string.retry);
menu.add(0, MENU_DELETE, 0, R.string.delete);
} else {
menu.add(0, MENU_PAUSE, 0, R.string.pause);
menu.add(0, MENU_STOP, 0, R.string.stop);
}
} else if (state == Downloader.QUEUED) {
// menu.add(0, MENU_STOP, 0, R.string.stop);
} else if (state == Downloader.PAUSED ||
state == Downloader.WAITING_FOR_USER) {
menu.add(0, MENU_RESUME, 0, R.string.resume);
menu.add(0, MENU_DELETE, 0, R.string.delete);
} else if (state == Downloader.DISK_PROBLEM){
menu.add(0, MENU_DELETE, 0, R.string.delete);
} else if (d.pendingFailed()) {
menu.add(0, MENU_RETRY, 0, R.string.retry);
menu.add(0, MENU_DELETE, 0, R.string.delete);
}
}
});
}
private DownloadObserver mObserver = new DownloadObserver() {
@Override
public void onChange() {
mHandler.post(new Runnable() {
@Override
public void run() {
if (mDownloadService != null) {
mData = mDownloadService.getDownloadInfos();
// Utils.D("observer onChange: " + mData.size());
mAdapter.notifyDataSetChanged();
}
}
});
}
};
@Override
protected void onDestroy() {
super.onDestroy();
if (mDownloadService != null)
mDownloadService.unregisterObserver(mObserver);
unbindService(mConnection);
}
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
mDownloadService = ((DownloadService.LocalBinder)service).getService();
mDownloadService.registerDownloadObserver(mObserver);
mAdapter = new DownloadListAdapter(DownloadActivity.this, R.layout.download_item);
setListAdapter(mAdapter);
mData = mDownloadService.getDownloadInfos();
mAdapter.notifyDataSetChanged();
}
public void onServiceDisconnected(ComponentName className) {
// This is called when the connection with the service has been
// unexpectedly disconnected -- that is, its process crashed.
// Because it is running in our same process, we should never
// see this happen.
mDownloadService = null;
}
};
public boolean onContextItemSelected(MenuItem item) {
super.onContextItemSelected(item);
AdapterContextMenuInfo menuInfo = (AdapterContextMenuInfo)item
.getMenuInfo();
DownloadInfo d = mData.get(menuInfo.position);
switch (item.getItemId()) {
case MENU_CLEAR: {
if (mDownloadService != null) {
mDownloadService.removeDownload(d);
synchronized(d) {
d.setScheduled(false);
mDownloadService.notifyChanged();
}
}
break;
}
case MENU_STOP: {
synchronized(d) {
d.stopDownload();
if (mDownloadService != null)
mDownloadService.notifyChanged();
}
mAdapter.notifyDataSetChanged();
break;
}
case MENU_RESUME: {
if (mDownloadService != null) {
mDownloadService.resumeDownload(d);
mAdapter.notifyDataSetChanged();
}
break;
}
case MENU_DELETE: {
if (mDownloadService != null) {
mDownloadService.removeDownload(d);
d.deleteDownload();
synchronized (d) {
// Force existing thread to stop.
mDownloadService.notifyChanged();
}
}
break;
}
case MENU_PAUSE: {
synchronized(d) {
d.pauseDownload();
}
mAdapter.notifyDataSetChanged();
break;
}
case MENU_RETRY: {
if (mDownloadService != null) {
mAdapter.notifyDataSetChanged();
mDownloadService.retryDownload(d);
}
break;
}
}
return true;
}
protected final class DownloadListAdapter extends BaseAdapter {
private int mResource;
private LayoutInflater mInflater;
public DownloadListAdapter(Context context, int resource) {
mResource = resource;
mInflater = (LayoutInflater)context.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getCount() {
if (mData == null)
return 0;
return mData.size();
}
@Override
public Object getItem(int position) {
if (mData == null)
return null;
if (position < mData.size())
return mData.get(position);
return null;
}
@Override
public long getItemId(int position) {
if (mData == null)
return -1;
if (position < mData.size())
return position;
return -1;
}
@Override
public int getViewTypeCount() {
return 1;
}
@Override
public int getItemViewType(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v;
Object item = mData.get(position);
if (convertView == null) {
v = mInflater.inflate(mResource, parent, false);
} else {
v = convertView;
}
DownloadInfo info = (DownloadInfo)item;
TextView musicInfo = (TextView)v.findViewById(R.id.music_info);
musicInfo.setText(info.getFileName());
ProgressBar progress = (ProgressBar)v.findViewById(R.id.progress);
int percent = info.getTotalBytes() == 0 ? 0 : 100 * info.getCurrentBytes() / info.getTotalBytes();
// Max can't be 0.
progress.setProgress(percent);
// Set status.
TextView musicStatus = (TextView)v.findViewById(R.id.music_status);
TextView bytesInfo = (TextView)v.findViewById(R.id.download_bytes);
TextView error = (TextView)v.findViewById(R.id.error);
int state = info.getState();
if (state == Downloader.COMPLETE) {
musicStatus.setText(R.string.finished);
musicStatus.setTextColor(getResources().getColor(R.color.download_finished));
//progress.setVisibility(View.GONE);
bytesInfo.setVisibility(View.GONE);
error.setVisibility(View.GONE);
Utils.assertD(info.getCurrentBytes() == info.getTotalBytes());
} else if (state == Downloader.GAVE_UP) {
musicStatus.setText(R.string.failed);
musicStatus.setTextColor(getResources().getColor(R.color.download_failed));
bytesInfo.setVisibility(View.GONE);
error.setVisibility(View.VISIBLE);
error.setText("Error: maximum retries reached");
} else if (state == Downloader.DISK_PROBLEM) {
musicStatus.setText(R.string.failed);
musicStatus.setTextColor(getResources().getColor(R.color.download_failed));
bytesInfo.setVisibility(View.GONE);
error.setVisibility(View.VISIBLE);
error.setText("Error: disk failure");
} else if (state == Downloader.CORRUPT_FILE) {
musicStatus.setText(R.string.failed);
musicStatus.setTextColor(getResources().getColor(R.color.download_failed));
bytesInfo.setVisibility(View.GONE);
error.setVisibility(View.VISIBLE);
error.setText("Error: file corrupted");
} else if (state == Downloader.WAITING_FOR_USER) {
musicStatus.setText(R.string.failed);
musicStatus.setTextColor(getResources().getColor(R.color.download_failed));
bytesInfo.setVisibility(View.GONE);
error.setVisibility(View.VISIBLE);
error.setText("Oops, you probably can resume");
} else if (state == Downloader.RECOVERY_FAILED) {
musicStatus.setText(R.string.failed);
musicStatus.setTextColor(getResources().getColor(R.color.download_failed));
bytesInfo.setVisibility(View.GONE);
error.setVisibility(View.VISIBLE);
error.setText("Error: recovery failed");
} else if (state == Downloader.DOWNLOADING ||
state == Downloader.CONNECTING ||
state == Downloader.REMOTE_QUEUED ||
state == Downloader.SAVING ||
state == Downloader.IDENTIFY_CORRUPTION ||
state == Downloader.WAITING_FOR_RESULTS ||
state == Downloader.WAITING_FOR_RETRY ||
state == Downloader.WAITING_FOR_CONNECTIONS ||
state == Downloader.ITERATIVE_GUESSING) {
if (!info.isScheduled()) {
musicStatus.setText(R.string.aborted);
musicStatus.setTextColor(getResources().getColor(R.color.download_failed));
bytesInfo.setVisibility(View.GONE);
error.setVisibility(View.GONE);
} else {
musicStatus.setText(R.string.downloading);
musicStatus.setTextColor(getResources().getColor(R.color.download_pending));
bytesInfo.setVisibility(View.VISIBLE);
error.setVisibility(View.GONE);
bytesInfo.setText("" + percent + "%");
}
} else if (state == Downloader.QUEUED) {
musicStatus.setText(R.string.queued);
musicStatus.setTextColor(getResources().getColor(R.color.download_pending));
bytesInfo.setVisibility(View.GONE);
error.setVisibility(View.GONE);
} else if (state == Downloader.ABORTED) {
musicStatus.setText(R.string.aborted);
musicStatus.setTextColor(getResources().getColor(R.color.download_failed));
bytesInfo.setVisibility(View.GONE);
error.setVisibility(View.GONE);
} else if (state == Downloader.PAUSED) {
musicStatus.setText(R.string.paused);
musicStatus.setTextColor(getResources().getColor(R.color.download_stopped));
bytesInfo.setVisibility(View.VISIBLE);
error.setVisibility(View.GONE);
bytesInfo.setText("" + percent + "%");
} else if (info.hasFailed()) {
musicStatus.setText(R.string.failed);
musicStatus.setTextColor(getResources().getColor(R.color.download_failed));
bytesInfo.setVisibility(View.GONE);
if (!TextUtils.isEmpty(info.getError())) {
error.setVisibility(View.VISIBLE);
error.setText(info.getError());
}
musicStatus.setText(R.string.failed);
} else if (state == DownloadInfo.PENDING) {
musicStatus.setText(R.string.pending);
musicStatus.setTextColor(getResources().getColor(R.color.download_pending));
bytesInfo.setVisibility(View.GONE);
error.setVisibility(View.GONE);
return v;
} else {
Log.e(Utils.TAG, "Should not reach here");
}
return v;
}
}
}