We are no longer offering accounts on this server. Consider https://gitlab.freedesktop.org/ as a place to host projects.

Commit 9778cbbd authored by Mike Sheldon's avatar Mike Sheldon

Add the ability to download songs directly to the SD card

Add a better quality low resolution icon
Add more detailed explanation of account details
Allow for scrolling if used on a small screen
parent 530d84f9
......@@ -15,4 +15,6 @@
</application>
<uses-sdk android:minSdkVersion="2" />
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
</manifest>
......@@ -14,37 +14,43 @@ public final class R {
public static final int album=0x7f020000;
public static final int back=0x7f020001;
public static final int icon=0x7f020002;
public static final int next=0x7f020003;
public static final int pause=0x7f020004;
public static final int play=0x7f020005;
public static final int prev=0x7f020006;
public static final int quit=0x7f020007;
public static final int logo=0x7f020003;
public static final int next=0x7f020004;
public static final int pause=0x7f020005;
public static final int play=0x7f020006;
public static final int prev=0x7f020007;
public static final int quit=0x7f020008;
public static final int save=0x7f020009;
}
public static final class id {
public static final int ImageView01=0x7f050003;
public static final int ImageView01=0x7f050004;
public static final int LinearLayout01=0x7f050000;
public static final int TableLayout01=0x7f05000b;
public static final int TableLayout02=0x7f05000f;
public static final int TableLayout03=0x7f050002;
public static final int TableRow01=0x7f05000d;
public static final int TableRow02=0x7f05000e;
public static final int TableRow03=0x7f050014;
public static final int TextView01=0x7f05000c;
public static final int TextView02=0x7f050004;
public static final int TextView03=0x7f050006;
public static final int TextView04=0x7f05000a;
public static final int TextView05=0x7f050009;
public static final int albumImage=0x7f050011;
public static final int artistText=0x7f050013;
public static final int loginButton=0x7f050008;
public static final int nextButton=0x7f050017;
public static final int passwordEntry=0x7f050007;
public static final int playPauseButton=0x7f050016;
public static final int prevButton=0x7f050015;
public static final int stationNameText=0x7f050010;
public static final int titleText=0x7f050012;
public static final int usernameEntry=0x7f050005;
public static final int viewAnimator=0x7f050001;
public static final int ScrollView01=0x7f050001;
public static final int TableLayout01=0x7f05000e;
public static final int TableLayout02=0x7f050012;
public static final int TableLayout03=0x7f050003;
public static final int TableRow01=0x7f050010;
public static final int TableRow02=0x7f050011;
public static final int TableRow03=0x7f050017;
public static final int TextView01=0x7f05000f;
public static final int TextView02=0x7f050007;
public static final int TextView03=0x7f050009;
public static final int TextView04=0x7f05000d;
public static final int TextView05=0x7f05000c;
public static final int TextView06=0x7f050005;
public static final int TextView07=0x7f050006;
public static final int albumImage=0x7f050014;
public static final int artistText=0x7f050016;
public static final int loginButton=0x7f05000b;
public static final int nextButton=0x7f05001a;
public static final int passwordEntry=0x7f05000a;
public static final int playPauseButton=0x7f050019;
public static final int prevButton=0x7f050018;
public static final int saveButton=0x7f05001b;
public static final int stationNameText=0x7f050013;
public static final int titleText=0x7f050015;
public static final int usernameEntry=0x7f050008;
public static final int viewAnimator=0x7f050002;
}
public static final class layout {
public static final int main=0x7f030000;
......
......@@ -5,12 +5,20 @@
<LinearLayout android:id="@+id/LinearLayout01" android:layout_width="fill_parent" android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android">
<ViewAnimator android:layout_height="wrap_content" android:id="@+id/viewAnimator" android:layout_width="fill_parent"><TableLayout android:id="@+id/TableLayout03" android:layout_height="wrap_content" android:layout_width="fill_parent"><ImageView android:id="@+id/ImageView01" android:layout_height="wrap_content" android:src="@drawable/icon" android:layout_width="fill_parent" android:layout_marginTop="5px"></ImageView><TextView android:id="@+id/TextView02" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Username:"></TextView><EditText android:layout_height="wrap_content" android:layout_width="fill_parent" android:id="@+id/usernameEntry" android:singleLine="true"></EditText><TextView android:id="@+id/TextView03" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Password:" android:layout_marginTop="10px"></TextView><EditText android:layout_width="wrap_content" android:layout_height="wrap_content" android:password="true" android:id="@+id/passwordEntry" android:singleLine="true"></EditText>
<ScrollView android:id="@+id/ScrollView01" android:layout_height="wrap_content" android:layout_width="fill_parent"><ViewAnimator android:layout_height="wrap_content" android:id="@+id/viewAnimator" android:layout_width="fill_parent"><TableLayout android:id="@+id/TableLayout03" android:layout_height="wrap_content" android:layout_width="fill_parent"><ImageView android:id="@+id/ImageView01" android:layout_height="wrap_content" android:layout_width="fill_parent" android:layout_marginTop="5px" android:src="@drawable/logo"></ImageView><TextView android:id="@+id/TextView06" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Libre.fm account details:" android:textStyle="bold" android:layout_marginTop="10px" android:layout_marginBottom="0px"></TextView><TextView android:id="@+id/TextView07" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="(This is not the same as your Google account)" android:layout_marginBottom="10px"></TextView><TextView android:id="@+id/TextView02" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Username:"></TextView><EditText android:layout_height="wrap_content" android:layout_width="fill_parent" android:id="@+id/usernameEntry" android:singleLine="true"></EditText><TextView android:id="@+id/TextView03" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Password:" android:layout_marginTop="10px"></TextView><EditText android:layout_width="wrap_content" android:layout_height="wrap_content" android:password="true" android:id="@+id/passwordEntry" android:singleLine="true"></EditText>
<Button android:layout_width="wrap_content" android:id="@+id/loginButton" android:text="Login" android:layout_height="wrap_content" android:layout_marginTop="20px"></Button>
<TextView android:id="@+id/TextView05" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Don't have an account?" android:layout_marginTop="20px" android:textStyle="bold"></TextView><TextView android:id="@+id/TextView04" android:layout_width="wrap_content" android:layout_height="wrap_content" android:autoLink="web" android:clickable="true" android:text="Visit www.libre.fm to sign up for a free account."></TextView>
</TableLayout><TableLayout android:id="@+id/TableLayout01" android:layout_height="wrap_content" android:layout_width="fill_parent" android:visibility="visible"><ImageView android:id="@+id/ImageView01" android:layout_height="wrap_content" android:src="@drawable/icon" android:layout_width="fill_parent" android:layout_marginTop="5px"></ImageView><TextView android:id="@+id/TextView01" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Popular Stations:"></TextView><TableRow android:id="@+id/TableRow01" android:layout_height="wrap_content" android:layout_width="fill_parent" android:layout_marginTop="10px" android:gravity="center_horizontal">
</TableLayout><TableLayout android:id="@+id/TableLayout01" android:layout_height="wrap_content" android:layout_width="fill_parent" android:visibility="visible"><ImageView android:id="@+id/ImageView01" android:layout_height="wrap_content" android:layout_width="fill_parent" android:layout_marginTop="5px" android:src="@drawable/logo"></ImageView><TextView android:id="@+id/TextView01" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Popular Stations:" android:textStyle="bold"></TextView><TableRow android:id="@+id/TableRow01" android:layout_height="wrap_content" android:layout_width="fill_parent" android:layout_marginTop="10px" android:gravity="center_horizontal">
......@@ -22,21 +30,17 @@
</TableRow></TableLayout>
<TableLayout android:id="@+id/TableLayout02" android:layout_height="wrap_content" android:layout_width="fill_parent" android:gravity="center_horizontal" android:layout_gravity="center_horizontal"><ImageView android:id="@+id/ImageView01" android:layout_height="wrap_content" android:src="@drawable/icon" android:layout_width="fill_parent" android:layout_marginTop="5px"></ImageView><TextView android:layout_height="wrap_content" android:id="@+id/stationNameText" android:textStyle="bold" android:layout_gravity="center_horizontal" android:layout_width="fill_parent" android:gravity="center_horizontal"></TextView><ImageView android:layout_height="wrap_content" android:id="@+id/albumImage" android:src="@drawable/album" android:layout_width="fill_parent" android:layout_marginTop="10px"></ImageView><TextView android:layout_height="wrap_content" android:id="@+id/titleText" style="bold" android:gravity="center_horizontal" android:layout_width="fill_parent" android:layout_gravity="center_horizontal" android:layout_marginTop="5px" android:textSize="7pt" android:maxLines="2"></TextView><TextView android:layout_height="wrap_content" android:id="@+id/artistText" android:gravity="center_horizontal" android:layout_width="fill_parent" android:layout_gravity="center_horizontal" android:maxLines="2"></TextView>
<TableLayout android:id="@+id/TableLayout02" android:layout_height="wrap_content" android:layout_width="fill_parent" android:gravity="center_horizontal" android:layout_gravity="center_horizontal"><ImageView android:id="@+id/ImageView01" android:layout_height="wrap_content" android:layout_width="fill_parent" android:layout_marginTop="5px" android:src="@drawable/logo"></ImageView><TextView android:layout_height="wrap_content" android:id="@+id/stationNameText" android:textStyle="bold" android:layout_gravity="center_horizontal" android:layout_width="fill_parent" android:gravity="center_horizontal"></TextView><ImageView android:layout_height="wrap_content" android:id="@+id/albumImage" android:src="@drawable/album" android:layout_width="fill_parent" android:layout_marginTop="10px"></ImageView><TextView android:layout_height="wrap_content" android:id="@+id/titleText" style="bold" android:gravity="center_horizontal" android:layout_width="fill_parent" android:layout_gravity="center_horizontal" android:layout_marginTop="5px" android:textSize="7pt" android:maxLines="2"></TextView><TextView android:layout_height="wrap_content" android:id="@+id/artistText" android:gravity="center_horizontal" android:layout_width="fill_parent" android:layout_gravity="center_horizontal" android:maxLines="2"></TextView>
<TableRow android:id="@+id/TableRow03" android:layout_height="wrap_content" android:layout_width="fill_parent" android:layout_marginTop="10px" android:layout_gravity="center_horizontal" android:gravity="center_horizontal"><ImageButton android:layout_height="wrap_content" android:id="@+id/prevButton" android:src="@drawable/prev" android:layout_width="fill_parent"></ImageButton>
<ImageButton android:layout_height="wrap_content" android:src="@drawable/pause" android:id="@+id/playPauseButton" android:layout_width="fill_parent" android:layout_marginLeft="20px" android:layout_marginRight="20px"></ImageButton><ImageButton android:layout_height="wrap_content" android:id="@+id/nextButton" android:src="@drawable/next" android:layout_width="fill_parent"></ImageButton>
<ImageButton android:layout_height="wrap_content" android:src="@drawable/pause" android:id="@+id/playPauseButton" android:layout_width="fill_parent" android:layout_marginLeft="20px" android:layout_marginRight="20px"></ImageButton><ImageButton android:layout_height="wrap_content" android:id="@+id/nextButton" android:src="@drawable/next" android:layout_width="fill_parent" android:layout_marginRight="20px"></ImageButton>
<ImageButton android:layout_height="wrap_content" android:id="@+id/saveButton" android:src="@drawable/save" android:layout_width="fill_parent"></ImageButton>
</TableRow>
</TableLayout>
</ViewAnimator>
</ViewAnimator></ScrollView>
</LinearLayout>
\ No newline at end of file
......@@ -22,10 +22,14 @@
package fm.libre.droid;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
......@@ -35,6 +39,7 @@ import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
......@@ -56,10 +61,14 @@ import android.content.SharedPreferences.Editor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.MediaPlayer;
import android.media.MediaScannerConnection;
import android.media.MediaPlayer.OnBufferingUpdateListener;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaScannerConnection.MediaScannerConnectionClient;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
......@@ -155,6 +164,12 @@ public class LibreDroid extends Activity implements OnBufferingUpdateListener, O
LibreDroid.this.togglePause();
}
});
final ImageButton saveButton = (ImageButton) findViewById(R.id.saveButton);
saveButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
LibreDroid.this.save();
}
});
}
@Override
......@@ -328,6 +343,12 @@ public class LibreDroid extends Activity implements OnBufferingUpdateListener, O
Toast.makeText(this, "Unable to connect to libre.fm server: " + ex.getMessage(), Toast.LENGTH_LONG).show();
}
}
public void save() {
Song song = this.playlist.getSong(this.currentSong);
Toast.makeText(LibreDroid.this, "Downloading \"" + song.title + "\" to your SD card.", Toast.LENGTH_LONG).show();
new DownloadTrackTask().execute(song);
}
public void onBufferingUpdate(MediaPlayer mp, int percent) {
if (percent > 2 && !mp.isPlaying() && this.playing) {
......@@ -382,7 +403,7 @@ public class LibreDroid extends Activity implements OnBufferingUpdateListener, O
try {
result = LibreDroid.this.httpGet("http://alpha.libre.fm/radio/adjust.php?session=" + LibreDroid.this.sessionKey + "&url=librefm://" + type + "/" + station);
} catch (Exception ex) {
Toast.makeText(LibreDroid.this, "Unable to tune station: " + ex.getMessage(), Toast.LENGTH_LONG).show();
Log.w("libredroid", "Unable to tune station: " + ex.getMessage());
}
return result;
}
......@@ -442,6 +463,82 @@ public class LibreDroid extends Activity implements OnBufferingUpdateListener, O
}
private class DownloadTrackTask extends AsyncTask<Song, String, List<Object>> implements MediaScannerConnectionClient {
private MediaScannerConnection msc;
private String path;
@Override
protected List<Object> doInBackground(Song... params) {
Song song = params[0];
List<Object> res = new ArrayList<Object>();
try {
File root = Environment.getExternalStorageDirectory();
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
res.add(false);
res.add("Please ensure an SD card is inserted before attempting to download songs. " + Environment.getExternalStorageState());
return res;
}
File musicDir = new File(root, "Music");
if (!musicDir.exists()) {
musicDir.mkdir();
}
File f = new File(musicDir, song.artist + " - " + song.title + ".ogg");
this.path = f.getAbsolutePath();
FileOutputStream fo = new FileOutputStream(f);
URL aURL = new URL(song.location);
HttpURLConnection conn = (HttpURLConnection) aURL.openConnection();
conn.connect();
if (conn.getResponseCode() == 301 || conn.getResponseCode() == 302 || conn.getResponseCode() == 307) {
// Redirected
aURL = new URL(conn.getHeaderField("Location"));
conn = (HttpURLConnection) aURL.openConnection();
}
InputStream is = conn.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
BufferedOutputStream bos = new BufferedOutputStream(fo);
byte buf[] = new byte[1024];
int count = 0;
while( (count = bis.read(buf, 0, 1024)) != -1)
{
bos.write(buf, 0, count);
}
bos.close();
fo.close();
bis.close();
is.close();
res.add(true);
res.add("Finished downloading \"" + song.title + "\"");
} catch (Exception ex) {
res.add(false);
res.add("Unable to download \"" + song.title + "\": " + ex.getMessage());
}
return res;
}
protected void onPostExecute(List<Object> result) {
Boolean res = (Boolean) result.get(0);
String msg = (String) result.get(1);
if (res.booleanValue() == true) {
// Update the media library so it knows about the new file
this.msc = new MediaScannerConnection(LibreDroid.this, this);
this.msc.connect();
}
Toast.makeText(LibreDroid.this, msg, Toast.LENGTH_LONG).show();
}
public void onMediaScannerConnected() {
this.msc.scanFile(this.path, null);
}
public void onScanCompleted(String path, Uri uri) {
}
}
private class MediaButtonReceiver extends BroadcastReceiver {
@Override
......
......@@ -56,7 +56,6 @@ public class Playlist extends DefaultHandler {
public void startElement(String uri, String name, String qName, Attributes atts) {
this.currentElement = name;
Log.d("libredroid", "Processing: " + name);
if (name.equals("track")) {
this.processingSong = new Song();
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment