allow changing the song artist and title
This commit is contained in:
parent
4e57796451
commit
126dbbf921
9 changed files with 180 additions and 7 deletions
8
app/proguard-rules.pro
vendored
8
app/proguard-rules.pro
vendored
|
@ -15,3 +15,11 @@
|
|||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
-keepclassmembers class * implements java.io.Serializable {
|
||||
static final long serialVersionUID;
|
||||
java.lang.Object writeReplace();
|
||||
java.lang.Object readResolve();
|
||||
private static final java.io.ObjectStreamField[] serialPersistentFields;
|
||||
private <fields>;
|
||||
public <fields>;
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
<action android:name="com.simplemobiletools.musicplayer.action.PLAYPAUSE"/>
|
||||
<action android:name="com.simplemobiletools.musicplayer.action.NEXT"/>
|
||||
<action android:name="com.simplemobiletools.musicplayer.action.STOP"/>
|
||||
<action android:name="com.simplemobiletools.musicplayer.action.EDIT"/>
|
||||
<action android:name="com.simplemobiletools.musicplayer.action.PLAYPOS"/>
|
||||
<action android:name="com.simplemobiletools.musicplayer.action.REFRESH_LIST"/>
|
||||
<action android:name="com.simplemobiletools.musicplayer.action.INCOMING_CALL_START"/>
|
||||
|
|
|
@ -6,6 +6,7 @@ public class Constants {
|
|||
public static final String WIDGET_TEXT_COLOR = "widget_text_color";
|
||||
public static final String SONG_POS = "song_position";
|
||||
public static final String DELETED_SONGS = "deleted_songs";
|
||||
public static final String EDITED_SONG = "edited_song";
|
||||
|
||||
private static final String PATH = "com.simplemobiletools.musicplayer.action.";
|
||||
|
||||
|
@ -16,6 +17,7 @@ public class Constants {
|
|||
public static final String PLAYPAUSE = PATH + "PLAYPAUSE";
|
||||
public static final String NEXT = PATH + "NEXT";
|
||||
public static final String STOP = PATH + "STOP";
|
||||
public static final String EDIT = PATH + "EDIT";
|
||||
public static final String PLAYPOS = PATH + "PLAYPOS";
|
||||
public static final String REFRESH_LIST = PATH + "REFRESH_LIST";
|
||||
public static final String CALL_START = PATH + "CALL_START";
|
||||
|
|
|
@ -1,16 +1,20 @@
|
|||
package com.simplemobiletools.musicplayer;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Color;
|
||||
import android.media.MediaScannerConnection;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.provider.MediaStore;
|
||||
import android.support.design.widget.CoordinatorLayout;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.util.SparseBooleanArray;
|
||||
import android.view.ActionMode;
|
||||
|
@ -20,6 +24,7 @@ import android.view.MenuItem;
|
|||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
@ -41,6 +46,7 @@ public class MainActivity extends AppCompatActivity
|
|||
private final int STORAGE_PERMISSION = 1;
|
||||
private Bus bus;
|
||||
private int selectedItemsCnt;
|
||||
private Song currentSong;
|
||||
private List<Song> songs;
|
||||
private Snackbar snackbar;
|
||||
private boolean isSnackbarShown;
|
||||
|
@ -141,7 +147,8 @@ public class MainActivity extends AppCompatActivity
|
|||
|
||||
@Subscribe
|
||||
public void songChangedEvent(Events.SongChanged event) {
|
||||
updateSongInfo(event.getSong());
|
||||
currentSong = event.getSong();
|
||||
updateSongInfo(currentSong);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
|
@ -191,6 +198,8 @@ public class MainActivity extends AppCompatActivity
|
|||
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.cab_edit:
|
||||
displayEditDialog();
|
||||
mode.finish();
|
||||
return true;
|
||||
case R.id.cab_remove:
|
||||
prepareForDeleting();
|
||||
|
@ -201,6 +210,99 @@ public class MainActivity extends AppCompatActivity
|
|||
}
|
||||
}
|
||||
|
||||
private void displayEditDialog() {
|
||||
final int songIndex = getSelectedSongIndex();
|
||||
if (songIndex == -1)
|
||||
return;
|
||||
|
||||
final Song selectedSong = songs.get(songIndex);
|
||||
if (selectedSong == null)
|
||||
return;
|
||||
|
||||
final String title = selectedSong.getTitle();
|
||||
final String artist = selectedSong.getArtist();
|
||||
|
||||
final View renameSongView = getLayoutInflater().inflate(R.layout.rename_song, null);
|
||||
final EditText titleET = (EditText) renameSongView.findViewById(R.id.title);
|
||||
titleET.setText(title);
|
||||
|
||||
final EditText artistET = (EditText) renameSongView.findViewById(R.id.artist);
|
||||
artistET.setText(artist);
|
||||
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setTitle(getResources().getString(R.string.rename_song));
|
||||
builder.setView(renameSongView);
|
||||
|
||||
builder.setPositiveButton("OK", null);
|
||||
builder.setNegativeButton("Cancel", null);
|
||||
|
||||
final AlertDialog alertDialog = builder.create();
|
||||
alertDialog.show();
|
||||
alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
final String newSongTitle = titleET.getText().toString().trim();
|
||||
final String newSongArtist = artistET.getText().toString().trim();
|
||||
|
||||
if (!newSongTitle.isEmpty() && !newSongArtist.isEmpty()) {
|
||||
final Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
|
||||
if (updateContentResolver(uri, selectedSong.getId(), newSongTitle, newSongArtist)) {
|
||||
getContentResolver().notifyChange(uri, null);
|
||||
boolean currSongChanged = false;
|
||||
if (currentSong != null && currentSong.equals(selectedSong)) {
|
||||
currSongChanged = true;
|
||||
}
|
||||
|
||||
final Song songInList = songs.get(songIndex);
|
||||
songInList.setTitle(newSongTitle);
|
||||
songInList.setArtist(newSongArtist);
|
||||
|
||||
if (currSongChanged) {
|
||||
notifyCurrentSongChanged(songInList);
|
||||
}
|
||||
|
||||
alertDialog.dismiss();
|
||||
} else {
|
||||
Utils.showToast(getApplicationContext(), R.string.rename_song_error);
|
||||
}
|
||||
} else {
|
||||
Utils.showToast(getApplicationContext(), R.string.rename_song_empty);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private boolean updateContentResolver(Uri uri, long songID, String newSongTitle, String newSongArtist) {
|
||||
final String where = MediaStore.Images.Media._ID + " = ? ";
|
||||
final String[] args = {String.valueOf(songID)};
|
||||
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(MediaStore.Audio.Media.TITLE, newSongTitle);
|
||||
values.put(MediaStore.Audio.Media.ARTIST, newSongArtist);
|
||||
|
||||
return getContentResolver().update(uri, values, where, args) == 1;
|
||||
}
|
||||
|
||||
private int getSelectedSongIndex() {
|
||||
final SparseBooleanArray items = songsList.getCheckedItemPositions();
|
||||
int cnt = items.size();
|
||||
for (int i = 0; i < cnt; i++) {
|
||||
if (items.valueAt(i)) {
|
||||
return items.keyAt(i);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private void notifyCurrentSongChanged(Song newSong) {
|
||||
final Intent intent = new Intent(this, MusicService.class);
|
||||
intent.putExtra(Constants.EDITED_SONG, newSong);
|
||||
intent.setAction(Constants.EDIT);
|
||||
startService(intent);
|
||||
currentSong = newSong;
|
||||
((SongAdapter) songsList.getAdapter()).notifyDataSetChanged();
|
||||
}
|
||||
|
||||
private void prepareForDeleting() {
|
||||
toBeDeleted.clear();
|
||||
final SparseBooleanArray items = songsList.getCheckedItemPositions();
|
||||
|
|
|
@ -104,10 +104,11 @@ public class MusicService extends Service
|
|||
pauseSong();
|
||||
break;
|
||||
case Constants.PLAYPAUSE:
|
||||
if (isPlaying())
|
||||
if (isPlaying()) {
|
||||
pauseSong();
|
||||
else
|
||||
} else {
|
||||
resumeSong();
|
||||
}
|
||||
break;
|
||||
case Constants.NEXT:
|
||||
playNextSong();
|
||||
|
@ -124,6 +125,11 @@ public class MusicService extends Service
|
|||
case Constants.CALL_STOP:
|
||||
incomingCallStop();
|
||||
break;
|
||||
case Constants.EDIT:
|
||||
currSong = (Song) intent.getSerializableExtra(Constants.EDITED_SONG);
|
||||
bus.post(new Events.SongChanged(currSong));
|
||||
setupNotification();
|
||||
break;
|
||||
case Constants.FINISH:
|
||||
destroyPlayer();
|
||||
break;
|
||||
|
|
|
@ -70,9 +70,6 @@ public class MyWidgetProvider extends AppWidgetProvider {
|
|||
|
||||
@Subscribe
|
||||
public void songChangedEvent(Events.SongChanged event) {
|
||||
if (currSong == event.getSong())
|
||||
return;
|
||||
|
||||
currSong = event.getSong();
|
||||
updateSongInfo();
|
||||
updateWidgets();
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package com.simplemobiletools.musicplayer;
|
||||
|
||||
public class Song {
|
||||
import java.io.Serializable;
|
||||
|
||||
public class Song implements Serializable {
|
||||
private static final long serialVersionUID = 6717978783256842145L;
|
||||
private long id;
|
||||
private String title;
|
||||
private String artist;
|
||||
|
@ -21,10 +24,18 @@ public class Song {
|
|||
return artist;
|
||||
}
|
||||
|
||||
public void setArtist(String newArtist) {
|
||||
artist = newArtist;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String newTitle) {
|
||||
title = newTitle;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
@ -38,4 +49,15 @@ public class Song {
|
|||
+ ", path=" + getPath()
|
||||
+ "}";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o)
|
||||
return true;
|
||||
|
||||
if (o == null)
|
||||
return false;
|
||||
|
||||
return this.toString().equals(o.toString());
|
||||
}
|
||||
}
|
||||
|
|
30
app/src/main/res/layout/rename_song.xml
Normal file
30
app/src/main/res/layout/rename_song.xml
Normal file
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/activity_margin">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/title"/>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/activity_margin"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/artist"/>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/artist"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/activity_margin"/>
|
||||
|
||||
</LinearLayout>
|
|
@ -5,6 +5,11 @@
|
|||
<string name="remove">Remove</string>
|
||||
<string name="edit">Edit</string>
|
||||
<string name="undo">Undo</string>
|
||||
<string name="title">Title</string>
|
||||
<string name="artist">Artist</string>
|
||||
<string name="rename_song">Rename song</string>
|
||||
<string name="rename_song_error">An error occurred during the renaming</string>
|
||||
<string name="rename_song_empty">Please fill in both an artist and a title</string>
|
||||
|
||||
<plurals name="songs_deleted">
|
||||
<item quantity="one">1 song deleted</item>
|
||||
|
|
Loading…
Reference in a new issue