diff --git a/app/build.gradle b/app/build.gradle index 9f0ac50..f5549e8 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -8,8 +8,8 @@ android { applicationId "com.sidzi.circleofmusic" minSdkVersion 17 targetSdkVersion 25 - versionCode 8 - versionName "Guitar" + versionCode 9 + versionName "Harpsichord" } buildTypes { @@ -21,6 +21,7 @@ android { } } + dependencies { compile 'com.android.volley:volley:1.0.0' compile 'com.j256.ormlite:ormlite-android:5.0' @@ -30,4 +31,5 @@ dependencies { compile 'com.android.support:support-v13:25.1.0' compile 'com.android.support:design:25.1.0' compile 'com.android.support:recyclerview-v7:25.1.0' + compile 'com.android.support:support-v4:25.1.0' } \ No newline at end of file diff --git a/app/src/androidTest/java/com/sidzi/circleofmusic/ApplicationTest.java b/app/src/androidTest/java/com/sidzi/circleofmusic/ApplicationTest.java deleted file mode 100644 index adcfbc6..0000000 --- a/app/src/androidTest/java/com/sidzi/circleofmusic/ApplicationTest.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.sidzi.circleofmusic; - -import android.app.Application; -import android.test.ApplicationTestCase; - -/** - * Testing Fundamentals - */ -public class ApplicationTest extends ApplicationTestCase { - public ApplicationTest() { - super(Application.class); - } -} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c5b4a0e..79139a8 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -25,6 +25,7 @@ android:name=".ui.MainActivity" android:label="@string/title_activity_main" android:launchMode="singleTask" + android:screenOrientation="portrait" android:theme="@style/splashScreen" android:windowSoftInputMode="adjustPan"> @@ -37,7 +38,9 @@ - + + + @@ -51,7 +54,19 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/ic_launcher-web.png b/app/src/main/ic_launcher-web.png index 620d232..688b1f3 100644 Binary files a/app/src/main/ic_launcher-web.png and b/app/src/main/ic_launcher-web.png differ diff --git a/app/src/main/java/com/sidzi/circleofmusic/adapters/PotmAdapter.java b/app/src/main/java/com/sidzi/circleofmusic/adapters/PotmAdapter.java index b605ecb..f0cfbe2 100644 --- a/app/src/main/java/com/sidzi/circleofmusic/adapters/PotmAdapter.java +++ b/app/src/main/java/com/sidzi/circleofmusic/adapters/PotmAdapter.java @@ -16,8 +16,10 @@ import com.android.volley.toolbox.JsonArrayRequest; import com.android.volley.toolbox.Volley; import com.sidzi.circleofmusic.R; -import com.sidzi.circleofmusic.config; import com.sidzi.circleofmusic.entities.Potm; +import com.sidzi.circleofmusic.helpers.MusicServiceConnection; +import com.sidzi.circleofmusic.services.MusicPlayerService; +import com.sidzi.circleofmusic.ui.MainActivity; import org.json.JSONArray; import org.json.JSONException; @@ -93,12 +95,10 @@ class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener @Override public void onClick(View v) { - Intent ready_track = new Intent("com.sidzi.circleofmusic.PLAY_TRACK"); - ready_track.putExtra("track_path", config.com_url + v.getTag(R.id.tag_track_path).toString()); - ready_track.putExtra("track_name", v.getTag(R.id.tag_track_name).toString()); - ready_track.putExtra("track_artist", v.getTag(R.id.tag_track_artist).toString()); - ready_track.putExtra("bucket", false); - mContext.sendBroadcast(ready_track); + Intent intent = new Intent(mContext, MusicPlayerService.class); + MusicServiceConnection mMusicServiceConnection = ((MainActivity) mContext).mMusicServiceConnection; + mContext.bindService(intent, mMusicServiceConnection, Context.BIND_AUTO_CREATE); + mMusicServiceConnection.getmMusicPlayerService().play(v.getTag(R.id.tag_track_path).toString(), v.getTag(R.id.tag_track_artist).toString(), v.getTag(R.id.tag_track_name).toString()); } } } diff --git a/app/src/main/java/com/sidzi/circleofmusic/adapters/TracksAdapter.java b/app/src/main/java/com/sidzi/circleofmusic/adapters/TracksAdapter.java index a01afc3..f088e9f 100644 --- a/app/src/main/java/com/sidzi/circleofmusic/adapters/TracksAdapter.java +++ b/app/src/main/java/com/sidzi/circleofmusic/adapters/TracksAdapter.java @@ -17,7 +17,10 @@ import com.j256.ormlite.stmt.QueryBuilder; import com.sidzi.circleofmusic.R; import com.sidzi.circleofmusic.entities.Track; +import com.sidzi.circleofmusic.helpers.MusicServiceConnection; import com.sidzi.circleofmusic.helpers.OrmHandler; +import com.sidzi.circleofmusic.services.MusicPlayerService; +import com.sidzi.circleofmusic.ui.MainActivity; import java.sql.SQLException; import java.util.ArrayList; @@ -114,12 +117,14 @@ class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener @Override public void onClick(View v) { - Intent ready_track = new Intent("com.sidzi.circleofmusic.PLAY_TRACK"); - ready_track.putExtra("track_path", v.getTag(R.id.tag_track_path).toString()); - ready_track.putExtra("track_name", v.getTag(R.id.tag_track_name).toString()); - ready_track.putExtra("track_artist", v.getTag(R.id.tag_track_artist).toString()); - ready_track.putExtra("bucket", bucketBool); - mContext.sendBroadcast(ready_track); + Intent intent = new Intent(mContext, MusicPlayerService.class); + MusicServiceConnection mMusicServiceConnection = ((MainActivity) mContext).mMusicServiceConnection; + mContext.bindService(intent, mMusicServiceConnection, Context.BIND_AUTO_CREATE); + if (!bucketBool) + mMusicServiceConnection.getmMusicPlayerService().play(v.getTag(R.id.tag_track_path).toString()); + else + mMusicServiceConnection.getmMusicPlayerService().bucketPlay(v.getTag(R.id.tag_track_path).toString()); + } @Override diff --git a/app/src/main/java/com/sidzi/circleofmusic/entities/Track.java b/app/src/main/java/com/sidzi/circleofmusic/entities/Track.java index bd5ceb8..f43759f 100644 --- a/app/src/main/java/com/sidzi/circleofmusic/entities/Track.java +++ b/app/src/main/java/com/sidzi/circleofmusic/entities/Track.java @@ -4,8 +4,14 @@ import com.j256.ormlite.field.DatabaseField; import com.j256.ormlite.table.DatabaseTable; +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.io.Serializable; + @DatabaseTable(tableName = "table_tracks") -public class Track { +public class Track implements Serializable, Externalizable { @DatabaseField(id = true) private String path; @DatabaseField @@ -22,12 +28,23 @@ public class Track { public Track() { } + public Track(String path) { + this.path = path; + } + + public Track(String name, String path, String artist) { + this.path = path; + this.name = name; + this.artist = artist; + } + public Track(String name, String path, String artist, String album, Boolean bucket) { this.path = path; this.name = name; this.artist = artist; this.bucket = bucket; this.album = album; + this.play_count = 0; } public String getName() { @@ -65,4 +82,21 @@ public void setPlay_count(Integer play_count) { public String getAlbum() { return album; } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Track) + return ((Track) obj).getPath().contentEquals(this.path); + throw new UnsupportedOperationException(); + } + + @Override + public void writeExternal(ObjectOutput objectOutput) throws IOException { + objectOutput.writeObject(this); + } + + @Override + public void readExternal(ObjectInput objectInput) throws IOException, ClassNotFoundException { + objectInput.readObject(); + } } diff --git a/app/src/main/java/com/sidzi/circleofmusic/helpers/AudioEventHandler.java b/app/src/main/java/com/sidzi/circleofmusic/helpers/AudioEventHandler.java deleted file mode 100644 index e1bf9d8..0000000 --- a/app/src/main/java/com/sidzi/circleofmusic/helpers/AudioEventHandler.java +++ /dev/null @@ -1,267 +0,0 @@ -package com.sidzi.circleofmusic.helpers; - -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.graphics.BitmapFactory; -import android.graphics.PorterDuff; -import android.media.AudioManager; -import android.media.MediaPlayer; -import android.support.v4.app.NotificationCompat; -import android.view.View; -import android.widget.FrameLayout; -import android.widget.ImageButton; -import android.widget.ProgressBar; -import android.widget.TextView; -import android.widget.Toast; - -import com.j256.ormlite.android.apptools.OpenHelperManager; -import com.j256.ormlite.dao.Dao; -import com.j256.ormlite.stmt.PreparedQuery; -import com.j256.ormlite.stmt.QueryBuilder; -import com.j256.ormlite.stmt.SelectArg; -import com.sidzi.circleofmusic.R; -import com.sidzi.circleofmusic.entities.Track; -import com.sidzi.circleofmusic.ui.MainActivity; - -import java.io.IOException; -import java.sql.SQLException; -import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; - -import static android.content.Context.NOTIFICATION_SERVICE; - -public class AudioEventHandler extends BroadcastReceiver { - static public MediaPlayer mMediaPlayer = null; - static public NotificationManager mNotificationManager = null; - static public TrackProgressObserver mTrackProgressObserver = null; - static public String mRunningTrackPath = null; - - static private List mTracksList = null; - static private int mPlayingPosition = 0; - NotificationCompat.Builder mBuilder = null; - int notifyId = 1; - private TextView tvPlayingTrackName = null; - private TextView tvPlayingArtistName = null; - private ImageButton ibPlay = null; - private ImageButton ibAddToBucket = null; - private ImageButton ibPlayNext = null; - private ProgressBar pbTrackPlay = null; - - public AudioEventHandler() { - super(); - if (mMediaPlayer == null) { - mMediaPlayer = new MediaPlayer(); - mTrackProgressObserver = new TrackProgressObserver(); - mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); - mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { - @Override - public void onPrepared(MediaPlayer mediaPlayer) { - mediaPlayer.start(); - pbTrackPlay.setIndeterminate(false); - } - }); - } - } - - @Override - public void onReceive(final Context context, Intent intent) { - - FrameLayout flPlayer = (FrameLayout) ((MainActivity) context).findViewById(R.id.flPlayer); - - flPlayer.setVisibility(View.VISIBLE); - - tvPlayingTrackName = (TextView) ((MainActivity) context).findViewById(R.id.tvPlayingTrackName); - tvPlayingArtistName = (TextView) ((MainActivity) context).findViewById(R.id.tvPlayingTrackArtist); - ibPlay = (ImageButton) ((MainActivity) context).findViewById(R.id.ibPlayPause); - ibAddToBucket = (ImageButton) ((MainActivity) context).findViewById(R.id.ibAddToBucket); - ibPlayNext = (ImageButton) ((MainActivity) context).findViewById(R.id.ibPlayNext); - pbTrackPlay = (ProgressBar) ((MainActivity) context).findViewById(R.id.pbTrackPlay); - - pbTrackPlay.getProgressDrawable().setColorFilter(context.getResources().getColor(R.color.primaryInverted), PorterDuff.Mode.SRC_IN); - - final String track_path = intent.getStringExtra("track_path"); - final String track_name = intent.getStringExtra("track_name"); - final String track_artist = intent.getStringExtra("track_artist"); - final boolean bucketBoolean = intent.getBooleanExtra("bucket", false); - mRunningTrackPath = track_path; - - // Music Notification - - mNotificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE); - PendingIntent mainActivity = PendingIntent.getActivity(context, 101, new Intent(context, MainActivity.class), PendingIntent.FLAG_UPDATE_CURRENT); - - mBuilder = new NotificationCompat.Builder(context) - .setSmallIcon(R.drawable.ic_statusbar) - .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) - .setContentIntent(mainActivity) - .setLargeIcon(BitmapFactory.decodeResource(context.getResources(), R.mipmap.ic_launcher)) - .setPriority(NotificationCompat.PRIORITY_HIGH); - - final OrmHandler ormHandler = OpenHelperManager.getHelper(context, OrmHandler.class); - - - ibPlay.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(final View v) { - if (mMediaPlayer.isPlaying()) { - mMediaPlayer.pause(); - ((ImageButton) v).setImageResource(R.drawable.ic_track_play); - } else { - mMediaPlayer.start(); - ((ImageButton) v).setImageResource(R.drawable.ic_track_stop); - } - } - }); - ibAddToBucket.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - if (mMediaPlayer != null) { - Utils.bucketOps(mRunningTrackPath, !(Boolean) ibAddToBucket.getTag(), context); - if (!(Boolean) ibAddToBucket.getTag()) { - ((ImageButton) v).setImageResource(R.drawable.ic_track_bucket_added); - Toast.makeText(context, "Added to bucket", Toast.LENGTH_SHORT).show(); - } else { - ((ImageButton) v).setImageResource(R.drawable.ic_track_bucket_add); - } - ibAddToBucket.setTag(!(Boolean) ibAddToBucket.getTag()); - } - } - }); - ibPlayNext.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - playNext(); - } - }); - boolean bucket = false; - try { - try { - Dao dbTrack = ormHandler.getDao(Track.class); - if (bucketBoolean) - mTracksList = dbTrack.queryForEq("bucket", true); - else - mTracksList = dbTrack.queryForAll(); - for (mPlayingPosition = 0; mPlayingPosition < mTracksList.size(); mPlayingPosition++) { - if (mTracksList.get(mPlayingPosition).getPath().equals(mRunningTrackPath)) { - break; - } - } - QueryBuilder queryBuilder = dbTrack.queryBuilder(); - SelectArg selectArg = new SelectArg(); - queryBuilder.where().eq("path", selectArg); - PreparedQuery preparedQuery = queryBuilder.prepare(); - selectArg.setValue(track_path); - Track temp_track = dbTrack.query(preparedQuery).get(0); - temp_track.setPlay_count(temp_track.getPlay_count() + 1); - try { - dbTrack.update(temp_track); - } catch (SQLException e1) { - e1.printStackTrace(); - } - bucket = !(temp_track.getBucket() == null || !temp_track.getBucket()); - } catch (IndexOutOfBoundsException e) { - ibAddToBucket.setVisibility(View.INVISIBLE); - } - } catch (SQLException e) { - e.printStackTrace(); - } - try { - playSong(track_path, track_name, track_artist, bucket); - } catch (IOException e) { - e.printStackTrace(); - } - } - - void playNext() { - try { - Track temp_track = mTracksList.get(mPlayingPosition + 1); - mPlayingPosition += 1; - if (temp_track.getBucket() == null) { - temp_track.setBucket(false); - } - playSong(temp_track.getPath(), temp_track.getName(), temp_track.getArtist(), temp_track.getBucket()); - } catch (IOException e) { - e.printStackTrace(); - } catch (IndexOutOfBoundsException e) { - mPlayingPosition = -1; - playNext(); - } - } - - void playSong(String track_path, String track_name, String track_artist, boolean bucket) throws IOException { - if (mMediaPlayer.isPlaying()) { - mMediaPlayer.stop(); - } - ibPlay.setImageResource(R.drawable.ic_track_stop); - tvPlayingTrackName.setText(track_name); - tvPlayingArtistName.setText(track_artist); - if (!bucket) { - ibAddToBucket.setImageResource(R.drawable.ic_track_bucket_add); - } else { - ibAddToBucket.setImageResource(R.drawable.ic_track_bucket_added); - } - ibAddToBucket.setTag(bucket); - mMediaPlayer.reset(); - mMediaPlayer.setDataSource(track_path); - mRunningTrackPath = track_path; - if (track_path.startsWith("https://")) { - mMediaPlayer.prepareAsync(); - pbTrackPlay.setIndeterminate(true); - } else { - mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { - @Override - public void onCompletion(MediaPlayer mediaPlayer) { - pbTrackPlay.setProgress(0); - mTrackProgressObserver.stop(); - playNext(); - } - }); - mMediaPlayer.prepare(); - mTrackProgressObserver.setup(); - new Thread(mTrackProgressObserver).start(); - } - mBuilder.setContentTitle(track_name) - .setContentText(track_artist); - mNotificationManager.notify(notifyId, mBuilder.build()); - } - - public class TrackProgressObserver implements Runnable { - private AtomicBoolean stop = new AtomicBoolean(false); - private int totalDuration; - - TrackProgressObserver() { - super(); - } - - void setup() { - totalDuration = mMediaPlayer.getDuration(); - if (totalDuration == -1) - pbTrackPlay.setIndeterminate(true); - else { - pbTrackPlay.setIndeterminate(false); - pbTrackPlay.setMax(totalDuration / 1000); - } - } - - public void stop() { - stop.set(true); - } - - @Override - public void run() { - while (!stop.get()) { - try { - pbTrackPlay.setProgress(mMediaPlayer.getCurrentPosition() / 1000); - Thread.sleep(1000); - } catch (InterruptedException e1) { - e1.printStackTrace(); - } catch (IllegalStateException e) { - this.stop(); - } - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/sidzi/circleofmusic/helpers/DatabaseSynchronization.java b/app/src/main/java/com/sidzi/circleofmusic/helpers/DatabaseSynchronization.java index 48db4e6..30e49dc 100644 --- a/app/src/main/java/com/sidzi/circleofmusic/helpers/DatabaseSynchronization.java +++ b/app/src/main/java/com/sidzi/circleofmusic/helpers/DatabaseSynchronization.java @@ -6,10 +6,13 @@ import com.j256.ormlite.android.apptools.OpenHelperManager; import com.j256.ormlite.dao.Dao; +import com.sidzi.circleofmusic.config; import com.sidzi.circleofmusic.entities.Track; +import java.io.File; import java.sql.SQLException; import java.util.ArrayList; +import java.util.List; public class DatabaseSynchronization extends AsyncTask { private Context mContext; @@ -22,14 +25,17 @@ public DatabaseSynchronization(Context mContext) { protected Void doInBackground(Void... voids) { ArrayList mTrackList = Utils.musicLoader(mContext); OrmHandler ormHandler = OpenHelperManager.getHelper(mContext, OrmHandler.class); - for (Track t : - mTrackList) { - try { - Dao dbTrack = ormHandler.getDao(Track.class); + try { + Dao dbTrack = ormHandler.getDao(Track.class); + List _temp = dbTrack.queryForAll(); + _temp.removeAll(mTrackList); + for (Track t : + mTrackList) { dbTrack.createIfNotExists(t); - } catch (SQLException e) { - e.printStackTrace(); } + dbTrack.delete(_temp); + } catch (SQLException e) { + e.printStackTrace(); } OpenHelperManager.releaseHelper(); return null; @@ -40,8 +46,15 @@ protected void onPostExecute(Void aVoid) { SharedPreferences settings = mContext.getSharedPreferences("com_prefs", 0); if (settings.getBoolean("init", true)) { BucketSaver bucketSaver = new BucketSaver(mContext); - if (bucketSaver.importFile()) - settings.edit().putBoolean("init", false).apply(); + if (bucketSaver.importFile()) { + File com_dir = new File(config.com_local_url); + if (!com_dir.exists()) { + if (!com_dir.mkdirs()) { + throw new UnsupportedOperationException("Could not create com folder"); + } + } + } + settings.edit().putBoolean("init", false).apply(); } super.onPostExecute(aVoid); } diff --git a/app/src/main/java/com/sidzi/circleofmusic/helpers/LocalMusicLoader.java b/app/src/main/java/com/sidzi/circleofmusic/helpers/LocalMusicLoader.java index ff7f3c3..9946c6d 100644 --- a/app/src/main/java/com/sidzi/circleofmusic/helpers/LocalMusicLoader.java +++ b/app/src/main/java/com/sidzi/circleofmusic/helpers/LocalMusicLoader.java @@ -9,7 +9,6 @@ import java.util.ArrayList; public class LocalMusicLoader extends AsyncTask> { - private final ArrayList mTrackList = new ArrayList<>(); private Context mContext; private TracksAdapter tracksAdapter; diff --git a/app/src/main/java/com/sidzi/circleofmusic/helpers/MusicServiceConnection.java b/app/src/main/java/com/sidzi/circleofmusic/helpers/MusicServiceConnection.java new file mode 100644 index 0000000..f4466ec --- /dev/null +++ b/app/src/main/java/com/sidzi/circleofmusic/helpers/MusicServiceConnection.java @@ -0,0 +1,42 @@ +package com.sidzi.circleofmusic.helpers; + + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.IBinder; +import android.support.v4.content.LocalBroadcastManager; + +import com.sidzi.circleofmusic.services.MusicPlayerService; + +public class MusicServiceConnection implements ServiceConnection { + private MusicPlayerService mMusicPlayerService; + private Context mContext; + + public MusicServiceConnection(Context mContext) { + super(); + this.mContext = mContext; + } + + @Override + public void onServiceConnected(ComponentName componentName, IBinder iBinder) { + MusicPlayerService.MusicBinder musicBinder = (MusicPlayerService.MusicBinder) iBinder; + mMusicPlayerService = musicBinder.getService(); + if (MusicPlayerService.PLAYING_TRACK != null) { + Intent intent = new Intent(MusicPlayerService.ACTION_UPDATE_METADATA); + intent.putExtra("track_metadata", MusicPlayerService.PLAYING_TRACK); + LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent); + if (!mMusicPlayerService.mMediaPlayer.isPlaying()) + LocalBroadcastManager.getInstance(mContext).sendBroadcast(new Intent(MusicPlayerService.ACTION_PAUSE)); + } + } + + @Override + public void onServiceDisconnected(ComponentName componentName) { + } + + public MusicPlayerService getmMusicPlayerService() { + return mMusicPlayerService; + } +} diff --git a/app/src/main/java/com/sidzi/circleofmusic/helpers/Utils.java b/app/src/main/java/com/sidzi/circleofmusic/helpers/Utils.java index ca008ae..78dbc9c 100644 --- a/app/src/main/java/com/sidzi/circleofmusic/helpers/Utils.java +++ b/app/src/main/java/com/sidzi/circleofmusic/helpers/Utils.java @@ -15,10 +15,10 @@ import java.util.ArrayList; import java.util.List; -class Utils { +public class Utils { static boolean BUCKET_OPS = false; - static void bucketOps(String path, Boolean bucket, Context mContext) { + public static void bucketOps(String path, Boolean bucket, Context mContext) { final OrmHandler ormHandler = OpenHelperManager.getHelper(mContext, OrmHandler.class); try { Dao dbTrack = ormHandler.getDao(Track.class); diff --git a/app/src/main/java/com/sidzi/circleofmusic/helpers/MediaButtonHandler.java b/app/src/main/java/com/sidzi/circleofmusic/recievers/AlarmReciever.java similarity index 51% rename from app/src/main/java/com/sidzi/circleofmusic/helpers/MediaButtonHandler.java rename to app/src/main/java/com/sidzi/circleofmusic/recievers/AlarmReciever.java index fe15d4a..c3cb9f3 100644 --- a/app/src/main/java/com/sidzi/circleofmusic/helpers/MediaButtonHandler.java +++ b/app/src/main/java/com/sidzi/circleofmusic/recievers/AlarmReciever.java @@ -1,12 +1,12 @@ -package com.sidzi.circleofmusic.helpers; +package com.sidzi.circleofmusic.recievers; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; -public class MediaButtonHandler extends BroadcastReceiver { +public class AlarmReciever extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { - Utils.bucketOps(AudioEventHandler.mRunningTrackPath, true, context); + System.out.print(":"); } } diff --git a/app/src/main/java/com/sidzi/circleofmusic/recievers/MediaButtonHandler.java b/app/src/main/java/com/sidzi/circleofmusic/recievers/MediaButtonHandler.java new file mode 100644 index 0000000..9f9928d --- /dev/null +++ b/app/src/main/java/com/sidzi/circleofmusic/recievers/MediaButtonHandler.java @@ -0,0 +1,31 @@ +package com.sidzi.circleofmusic.recievers; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.media.SoundPool; + +import com.sidzi.circleofmusic.R; +import com.sidzi.circleofmusic.helpers.Utils; +import com.sidzi.circleofmusic.services.MusicPlayerService; + +import static android.os.Build.VERSION.SDK_INT; + +public class MediaButtonHandler extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + if (MusicPlayerService.PLAYING_TRACK != null) { + Utils.bucketOps(MusicPlayerService.PLAYING_TRACK.getPath(), true, context); + if (SDK_INT >= 21) { + SoundPool soundPool = new SoundPool.Builder().build(); + final int SoundID = soundPool.load(context, R.raw.fart, 0); + soundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() { + @Override + public void onLoadComplete(SoundPool soundPool, int i, int i1) { + soundPool.play(SoundID, 1, 1, 0, 0, 1); + } + }); + } + } + } +} diff --git a/app/src/main/java/com/sidzi/circleofmusic/recievers/MusicPlayerViewHandler.java b/app/src/main/java/com/sidzi/circleofmusic/recievers/MusicPlayerViewHandler.java new file mode 100644 index 0000000..7120abf --- /dev/null +++ b/app/src/main/java/com/sidzi/circleofmusic/recievers/MusicPlayerViewHandler.java @@ -0,0 +1,126 @@ +package com.sidzi.circleofmusic.recievers; + +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.graphics.BitmapFactory; +import android.graphics.PorterDuff; +import android.support.v4.app.NotificationCompat; +import android.view.View; +import android.widget.ImageButton; +import android.widget.ProgressBar; +import android.widget.TextView; +import android.widget.Toast; + +import com.sidzi.circleofmusic.R; +import com.sidzi.circleofmusic.entities.Track; +import com.sidzi.circleofmusic.helpers.MusicServiceConnection; +import com.sidzi.circleofmusic.services.MusicPlayerService; +import com.sidzi.circleofmusic.ui.MainActivity; + +import static android.content.Context.NOTIFICATION_SERVICE; + +public class MusicPlayerViewHandler extends BroadcastReceiver { + + private Context mContext; + private TextView tvPlayingTrackName; + private TextView tvPlayingArtistName; + private ImageButton ibPlay; + private ImageButton ibAddToBucket; + private ImageButton ibPlayNext; + private ProgressBar pbTrackPlay; + private NotificationManager mNotificationManager; + private NotificationCompat.Builder mBuilder; + private MusicServiceConnection mMusicServiceConnection; + + public MusicPlayerViewHandler(Context mContext) { + super(); + this.mContext = mContext; + + tvPlayingTrackName = (TextView) ((MainActivity) mContext).findViewById(R.id.tvPlayingTrackName); + tvPlayingArtistName = (TextView) ((MainActivity) mContext).findViewById(R.id.tvPlayingTrackArtist); + ibPlay = (ImageButton) ((MainActivity) mContext).findViewById(R.id.ibPlayPause); + ibAddToBucket = (ImageButton) ((MainActivity) mContext).findViewById(R.id.ibAddToBucket); + ibPlayNext = (ImageButton) ((MainActivity) mContext).findViewById(R.id.ibPlayNext); + pbTrackPlay = (ProgressBar) ((MainActivity) mContext).findViewById(R.id.pbTrackPlay); + pbTrackPlay.getProgressDrawable().setColorFilter(mContext.getResources().getColor(R.color.primaryInverted), PorterDuff.Mode.SRC_IN); + + // Music Notification + + mNotificationManager = (NotificationManager) mContext.getSystemService(NOTIFICATION_SERVICE); + PendingIntent mainActivity = PendingIntent.getActivity(mContext, 101, new Intent(mContext, MainActivity.class), PendingIntent.FLAG_UPDATE_CURRENT); + + mBuilder = new NotificationCompat.Builder(mContext) + .setSmallIcon(R.drawable.ic_statusbar) + .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) + .setContentIntent(mainActivity) + .setOngoing(true) + .setLargeIcon(BitmapFactory.decodeResource(mContext.getResources(), R.mipmap.ic_launcher)); + + mMusicServiceConnection = new MusicServiceConnection(mContext); + + } + + @Override + public void onReceive(final Context context, Intent intent) { + + final Track temp_track = MusicPlayerService.PLAYING_TRACK; + context.bindService(new Intent(mContext, MusicPlayerService.class), mMusicServiceConnection, Context.BIND_AUTO_CREATE); + final MusicPlayerService mpService = mMusicServiceConnection.getmMusicPlayerService(); + + ibPlay.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(final View v) { + if (mpService.mMediaPlayer.isPlaying()) { + mpService.pause(); + } else { + mpService.unpause(); + } + } + }); + ibAddToBucket.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (mpService.bucketOperation()) { + ((ImageButton) v).setImageResource(R.drawable.ic_track_bucket_added); + Toast.makeText(context, "Added to bucket", Toast.LENGTH_SHORT).show(); + } else { + ((ImageButton) v).setImageResource(R.drawable.ic_track_bucket_add); + } + } + }); + ibPlayNext.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + mpService.next(MusicPlayerService.PLAYING_BUCKET); + } + }); + switch (intent.getAction()) { + case MusicPlayerService.ACTION_UPDATE_METADATA: + tvPlayingTrackName.setText(temp_track.getName()); + tvPlayingArtistName.setText(temp_track.getArtist()); + if (!temp_track.getBucket()) { + ibAddToBucket.setImageResource(R.drawable.ic_track_bucket_add); + } else { + ibAddToBucket.setImageResource(R.drawable.ic_track_bucket_added); + } + ibAddToBucket.setTag(temp_track.getBucket()); + mBuilder.setContentTitle(temp_track.getName()) + .setContentText(temp_track.getArtist()); + int notifyId = 1; + mNotificationManager.notify(notifyId, mBuilder.build()); + break; + case MusicPlayerService.ACTION_PAUSE: + ibPlay.setImageResource(R.drawable.ic_track_play); + break; + case MusicPlayerService.ACTION_PLAY: + ibPlay.setImageResource(R.drawable.ic_track_stop); + break; + case MusicPlayerService.ACTION_CLOSE: + mNotificationManager.cancelAll(); + break; + } + } +} diff --git a/app/src/main/java/com/sidzi/circleofmusic/services/MusicPlayerService.java b/app/src/main/java/com/sidzi/circleofmusic/services/MusicPlayerService.java new file mode 100644 index 0000000..ec2bd38 --- /dev/null +++ b/app/src/main/java/com/sidzi/circleofmusic/services/MusicPlayerService.java @@ -0,0 +1,210 @@ +package com.sidzi.circleofmusic.services; + + +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.media.AudioManager; +import android.media.MediaPlayer; +import android.os.Binder; +import android.os.IBinder; +import android.support.annotation.Nullable; +import android.support.v4.content.LocalBroadcastManager; + +import com.j256.ormlite.android.apptools.OpenHelperManager; +import com.j256.ormlite.dao.Dao; +import com.sidzi.circleofmusic.config; +import com.sidzi.circleofmusic.entities.Track; +import com.sidzi.circleofmusic.helpers.OrmHandler; +import com.sidzi.circleofmusic.helpers.Utils; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.List; + +public class MusicPlayerService extends Service { + + final public static String ACTION_UPDATE_METADATA = "com.sidzi.circleofmusic.UPDATE_METADATA"; + final public static String ACTION_PAUSE = "com.sidzi.circleofmusic.PAUSE"; + final public static String ACTION_PLAY = "com.sidzi.circleofmusic.PLAY"; + public static final String ACTION_CLOSE = "com.sidzi.circleofmusic.CLOSE"; + public static Track PLAYING_TRACK = null; + public static boolean PLAYING_BUCKET; + private final IBinder mMIBinder = new MusicBinder(); + public MediaPlayer mMediaPlayer = null; + private int PLAYING_TRACK_POSITION = -1; + private LocalBroadcastManager localBroadcastManager; + private List mTrackList; + private List mBucketList; + private Context mContext; + private int songsTillSleep = -1; + + + public MusicPlayerService() { + } + + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + return super.onStartCommand(intent, flags, startId); + } + + @Override + public void onCreate() { + super.onCreate(); + mContext = this; + localBroadcastManager = LocalBroadcastManager.getInstance(this); + final OrmHandler ormHandler = OpenHelperManager.getHelper(this, OrmHandler.class); + Dao dbTrack; + try { + dbTrack = ormHandler.getDao(Track.class); + mTrackList = dbTrack.queryForAll(); + mBucketList = dbTrack.queryForEq("bucket", true); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Override + public void onDestroy() { + if (mMediaPlayer != null) { + mMediaPlayer.reset(); + mMediaPlayer.release(); + mMediaPlayer = null; + } + PLAYING_TRACK = null; + super.onDestroy(); + } + + + public void play(String track_path) { + if (mMediaPlayer == null) + init(); + mMediaPlayer.reset(); + try { + mMediaPlayer.setDataSource(track_path); + mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { + @Override + public void onCompletion(MediaPlayer mediaPlayer) { + next(false); + } + }); + mMediaPlayer.prepare(); + PLAYING_TRACK_POSITION = mTrackList.indexOf(new Track(track_path)); + PLAYING_TRACK = mTrackList.get(PLAYING_TRACK_POSITION); + PLAYING_BUCKET = false; + uiUpdate(true); + if (songsTillSleep == 0) + onDestroy(); + else + songsTillSleep--; + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void play(String Path, String Artist, String Name) { + if (mMediaPlayer == null) + init(); + mMediaPlayer.reset(); + try { + mMediaPlayer.setDataSource(config.com_url + Path); + mMediaPlayer.prepareAsync(); + PLAYING_TRACK = new Track(Name, Path, Artist); + PLAYING_TRACK.setBucket(false); + uiUpdate(true); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void bucketPlay(String track_path) { + if (mMediaPlayer == null) + init(); + mMediaPlayer.reset(); + try { + mMediaPlayer.setDataSource(track_path); + mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { + @Override + public void onCompletion(MediaPlayer mediaPlayer) { + next(true); + } + }); + mMediaPlayer.prepare(); + try { + PLAYING_TRACK_POSITION = mBucketList.indexOf(new Track(track_path)); + PLAYING_TRACK = mBucketList.get(PLAYING_TRACK_POSITION); + } catch (IndexOutOfBoundsException | NullPointerException ignore) { + } + PLAYING_BUCKET = true; + uiUpdate(true); + if (songsTillSleep == 0) + onDestroy(); + else + songsTillSleep--; + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void next(boolean bucket) { + try { + if (!bucket) + play(mTrackList.get(++PLAYING_TRACK_POSITION).getPath()); + else + bucketPlay(mBucketList.get(++PLAYING_TRACK_POSITION).getPath()); + } catch (IndexOutOfBoundsException ignore) { + } + } + + public void pause() { + mMediaPlayer.pause(); + uiUpdate(false); + } + + public void unpause() { + mMediaPlayer.start(); + uiUpdate(false); + } + + public boolean bucketOperation() { + Utils.bucketOps(PLAYING_TRACK.getPath(), !PLAYING_TRACK.getBucket(), mContext); + PLAYING_TRACK.setBucket(!PLAYING_TRACK.getBucket()); + return PLAYING_TRACK.getBucket(); + } + + private void uiUpdate(boolean b) { + String action = (!b) ? (mMediaPlayer.isPlaying() ? ACTION_PLAY : ACTION_PAUSE) : ACTION_UPDATE_METADATA; + Intent intent = new Intent(action); + localBroadcastManager.sendBroadcast(intent); + } + + public void setSongsTillSleep(int count) { + songsTillSleep = count; + } + + private void init() { + mMediaPlayer = new MediaPlayer(); + mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); + mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { + @Override + public void onPrepared(MediaPlayer mediaPlayer) { + mediaPlayer.start(); + uiUpdate(false); + } + }); + } + + @Nullable + @Override + public IBinder onBind(Intent intent) { + return mMIBinder; + } + + public class MusicBinder extends Binder { + public MusicPlayerService getService() { + return MusicPlayerService.this; + } + } +} + diff --git a/app/src/main/java/com/sidzi/circleofmusic/ui/AlarmActivity.java b/app/src/main/java/com/sidzi/circleofmusic/ui/AlarmActivity.java new file mode 100644 index 0000000..81ae984 --- /dev/null +++ b/app/src/main/java/com/sidzi/circleofmusic/ui/AlarmActivity.java @@ -0,0 +1,211 @@ +package com.sidzi.circleofmusic.ui; + +import android.annotation.SuppressLint; +import android.media.MediaPlayer; +import android.os.Bundle; +import android.os.Handler; +import android.support.v7.app.ActionBar; +import android.support.v7.app.AppCompatActivity; +import android.view.MotionEvent; +import android.view.View; +import android.view.WindowManager; + +import com.sidzi.circleofmusic.R; + +import java.io.IOException; + +/** + * An example full-screen activity that shows and hides the system UI (i.e. + * status bar and navigation/system bar) with user interaction. + */ +public class AlarmActivity extends AppCompatActivity { + /** + * Whether or not the system UI should be auto-hidden after + * {@link #AUTO_HIDE_DELAY_MILLIS} milliseconds. + */ + private static final boolean AUTO_HIDE = true; + + /** + * If {@link #AUTO_HIDE} is set, the number of milliseconds to wait after + * user interaction before hiding the system UI. + */ + private static final int AUTO_HIDE_DELAY_MILLIS = 0; + + /** + * Some older devices needs a small delay between UI widget updates + * and a change of the status and navigation bar. + */ + private static final int UI_ANIMATION_DELAY = 300; + private final Handler mHideHandler = new Handler(); + /** + * Touch listener to use for in-layout UI controls to delay hiding the + * system UI. This is to prevent the jarring behavior of controls going away + * while interacting with activity UI. + */ + private final View.OnTouchListener mDelayHideTouchListener = new View.OnTouchListener() { + @Override + public boolean onTouch(View view, MotionEvent motionEvent) { + if (AUTO_HIDE) { + delayedHide(AUTO_HIDE_DELAY_MILLIS); + } + return false; + } + }; + private View mContentView; + private final Runnable mHidePart2Runnable = new Runnable() { + @SuppressLint("InlinedApi") + @Override + public void run() { + // Delayed removal of status and navigation bar + + // Note that some of these constants are new as of API 16 (Jelly Bean) + // and API 19 (KitKat). It is safe to use them, as they are inlined + // at compile-time and do nothing on earlier devices. + mContentView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE + | View.SYSTEM_UI_FLAG_FULLSCREEN + | View.SYSTEM_UI_FLAG_LAYOUT_STABLE + | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION); + } + }; + private View mControlsView; + private final Runnable mShowPart2Runnable = new Runnable() { + @Override + public void run() { + // Delayed display of UI elements + ActionBar actionBar = getSupportActionBar(); + if (actionBar != null) { + actionBar.show(); + } + mControlsView.setVisibility(View.VISIBLE); + } + }; + private boolean mVisible; + private final Runnable mHideRunnable = new Runnable() { + @Override + public void run() { + hide(); + } + }; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.activity_alarm); + + mVisible = true; + mControlsView = findViewById(R.id.fullscreen_content_controls); + mContentView = findViewById(R.id.fullscreen_content); + + getWindow().addFlags( + WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON + ); + + // Set up the user interaction to manually show or hide the system UI. + mContentView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + toggle(); + } + }); + + // Upon interacting with UI controls, delay any scheduled hide() + // operations to prevent the jarring behavior of controls going away + // while interacting with the UI. + findViewById(R.id.bStopAlarm).setOnTouchListener(mDelayHideTouchListener); + + // Alarm Sound + final MediaPlayer mediaPlayer = new MediaPlayer(); + mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { + @Override + public void onPrepared(MediaPlayer mediaPlayer) { + mediaPlayer.start(); + } + }); + try { + mediaPlayer.setDataSource(getIntent().getStringExtra("alarm_path")); + mediaPlayer.setLooping(true); + mediaPlayer.prepare(); + } catch (IOException e) { + e.printStackTrace(); + } + + // End button + + findViewById(R.id.bStopAlarm).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + mediaPlayer.reset(); + try { + mediaPlayer.setDataSource(getIntent().getStringExtra("after_alarm_path")); + mediaPlayer.setLooping(false); + mediaPlayer.prepare(); + mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { + @Override + public void onCompletion(MediaPlayer mediaPlayer) { + mediaPlayer.reset(); + mediaPlayer.release(); + } + }); + } catch (IOException e) { + e.printStackTrace(); + } + } + }); + } + + @Override + protected void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + + // Trigger the initial hide() shortly after the activity has been + // created, to briefly hint to the user that UI controls + // are available. + delayedHide(100); + } + + private void toggle() { + if (mVisible) { + hide(); + } else { + show(); + } + } + + private void hide() { + // Hide UI first + ActionBar actionBar = getSupportActionBar(); + if (actionBar != null) { + actionBar.hide(); + } + mControlsView.setVisibility(View.GONE); + mVisible = false; + + // Schedule a runnable to remove the status and navigation bar after a delay + mHideHandler.removeCallbacks(mShowPart2Runnable); + mHideHandler.postDelayed(mHidePart2Runnable, UI_ANIMATION_DELAY); + } + + @SuppressLint("InlinedApi") + private void show() { + // Show the system bar + mContentView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION); + mVisible = true; + + // Schedule a runnable to display UI elements after a delay + mHideHandler.removeCallbacks(mHidePart2Runnable); + mHideHandler.postDelayed(mShowPart2Runnable, UI_ANIMATION_DELAY); + } + + /** + * Schedules a call to hide() in [delay] milliseconds, canceling any + * previously scheduled calls. + */ + private void delayedHide(int delayMillis) { + mHideHandler.removeCallbacks(mHideRunnable); + mHideHandler.postDelayed(mHideRunnable, delayMillis); + } +} diff --git a/app/src/main/java/com/sidzi/circleofmusic/ui/AlarmSettingActivity.java b/app/src/main/java/com/sidzi/circleofmusic/ui/AlarmSettingActivity.java new file mode 100644 index 0000000..6b53b5c --- /dev/null +++ b/app/src/main/java/com/sidzi/circleofmusic/ui/AlarmSettingActivity.java @@ -0,0 +1,192 @@ +package com.sidzi.circleofmusic.ui; + +import android.app.AlarmManager; +import android.app.DownloadManager; +import android.app.PendingIntent; +import android.content.DialogInterface; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.support.v7.app.AlertDialog; +import android.support.v7.app.AppCompatActivity; +import android.view.View; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.EditText; +import android.widget.Toast; + +import com.android.volley.Request; +import com.android.volley.RequestQueue; +import com.android.volley.Response; +import com.android.volley.VolleyError; +import com.android.volley.toolbox.JsonObjectRequest; +import com.android.volley.toolbox.Volley; +import com.sidzi.circleofmusic.R; +import com.sidzi.circleofmusic.config; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.File; +import java.io.FilenameFilter; +import java.util.Calendar; + +import static android.os.Build.VERSION.SDK_INT; + +public class AlarmSettingActivity extends AppCompatActivity { + private static final int REQUEST_ALARM_PATH = 4114; + EditText etTimePicker; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_alarm_setting); + etTimePicker = (EditText) findViewById(R.id.etTimePicker); + + Button bSelectAlarm = (Button) findViewById(R.id.bSelectAlarm); + final AlertDialog.Builder builder = new AlertDialog.Builder(this); + final AlertDialog.Builder innerBuilder = new AlertDialog.Builder(this); + + final DownloadManager downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE); + + bSelectAlarm.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (etTimePicker.getText().toString().equals("")) { + Toast.makeText(getApplicationContext(), "Enter the time first", Toast.LENGTH_SHORT).show(); + } else { + builder.setTitle("Select a sound") + .setMessage("Select from a list of CoM alarms or choose from your own collection") + .setPositiveButton("CoM Alarms", new DialogInterface.OnClickListener() { + @Override + public void onClick(final DialogInterface dialogInterface, int i) { +// Load CoM alarms + RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext()); + JsonObjectRequest alarmArray = new JsonObjectRequest(Request.Method.GET, config.com_url + "getAlarms", null, new Response.Listener() { + @Override + public void onResponse(JSONObject response) { + try { + final JSONArray alarms = response.getJSONArray("alarms"); + final ArrayAdapter arrayAdapter = new ArrayAdapter<>(getApplicationContext(), R.layout.layout_row_alarm_selection); + for (int i = 0; i < alarms.length(); i++) + arrayAdapter.add(alarms.get(i).toString()); + innerBuilder.setAdapter(arrayAdapter, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + if (!new File(config.com_local_url + arrayAdapter.getItem(i)).exists()) { + DownloadManager.Request request = new DownloadManager.Request(Uri.parse(config.com_url + "getAlarm" + arrayAdapter.getItem(i))); + request.setTitle("Downloading Alarm Sound"); + request.setDestinationInExternalPublicDir("", "com-data/alarms/" + arrayAdapter.getItem(i)); + downloadManager.enqueue(request); + } + if (!new File(config.com_local_url + "secondary_" + arrayAdapter.getItem(i)).exists()) { + DownloadManager.Request request2 = new DownloadManager.Request(Uri.parse(config.com_url + "getAlarmSecondary" + arrayAdapter.getItem(i))); + request2.setTitle("Downloading Secondary Alarm Sound"); + request2.setDestinationInExternalPublicDir("", "com-data/alarms/secondary_" + arrayAdapter.getItem(i)); + downloadManager.enqueue(request2); + } + setAlarm(config.com_local_url + arrayAdapter.getItem(i), config.com_local_url + "secondary_" + arrayAdapter.getItem(i)); + finish(); + } + }); + innerBuilder.create().show(); + } catch (JSONException e) { + e.printStackTrace(); + } + + } + }, new Response.ErrorListener() { + @Override + public void onErrorResponse(VolleyError error) { + File[] alarms = new File(config.com_local_url).listFiles(new FilenameFilter() { + @Override + public boolean accept(File file, String s) { + return !s.startsWith("secondary_"); + } + }); + final ArrayAdapter arrayAdapter = new ArrayAdapter<>(getApplicationContext(), R.layout.layout_row_alarm_selection); + for (File alarm : alarms) + arrayAdapter.add(alarm.getName()); + innerBuilder.setAdapter(arrayAdapter, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + setAlarm(config.com_local_url + arrayAdapter.getItem(i), config.com_local_url + "secondary_" + arrayAdapter.getItem(i)); + finish(); + } + }); + innerBuilder.create().show(); + } + }); + requestQueue.add(alarmArray); + dialogInterface.dismiss(); + } + }) + .setNegativeButton("Personal Music", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { +// Load file browser + Intent intent = new Intent(AlarmSettingActivity.this, ListFileActivity.class); + startActivityForResult(intent, REQUEST_ALARM_PATH); + + } + }); + builder.create().show(); + } + } + }); + } + + void setAlarm(String alarm, String secondary_alarm) { + + Intent intent = new Intent(this, AlarmActivity.class); + + intent.putExtra("alarm_path", alarm); + intent.putExtra("after_alarm_path", secondary_alarm); + + + AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE); + Calendar calendar = Calendar.getInstance(); + + PendingIntent pendingIntent = PendingIntent.getActivity(this, 443, intent, PendingIntent.FLAG_ONE_SHOT); + + int hour = Integer.parseInt(etTimePicker.getText().subSequence(0, 2).toString()); + int minute = Integer.parseInt(etTimePicker.getText().subSequence(2, 4).toString()); + + int dH = diffH(calendar.get(Calendar.HOUR_OF_DAY), hour); + + if (calendar.get(Calendar.HOUR_OF_DAY) > hour) + calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DATE) + 1, hour, minute); + else + calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DATE), hour, minute); + + if (SDK_INT >= 19) + alarmManager.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent); + else + alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent); + + Toast.makeText(getApplicationContext(), "Setting Alarm for " + dH + " hrs from now", Toast.LENGTH_LONG).show(); + } + + int diffH(int c, int s) { + if (c <= s) { + return s - c; + } else { + return s + 24 - c; + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == REQUEST_ALARM_PATH && resultCode == RESULT_OK) { + String path; + path = data.getStringExtra("filepath"); + if (!path.equals("") && !(new File(path).isDirectory())) + setAlarm(path, ""); + else + startActivityForResult(new Intent(this, ListFileActivity.class), REQUEST_ALARM_PATH); + } + } + +} diff --git a/app/src/main/java/com/sidzi/circleofmusic/ui/ListFileActivity.java b/app/src/main/java/com/sidzi/circleofmusic/ui/ListFileActivity.java new file mode 100644 index 0000000..f2c805c --- /dev/null +++ b/app/src/main/java/com/sidzi/circleofmusic/ui/ListFileActivity.java @@ -0,0 +1,144 @@ +package com.sidzi.circleofmusic.ui; + +import android.content.Intent; +import android.os.Build; +import android.os.Bundle; +import android.os.Environment; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import com.sidzi.circleofmusic.R; +import com.sidzi.circleofmusic.helpers.VerticalSpaceDecorationHelper; + +import java.io.File; +import java.util.ArrayList; + +public class ListFileActivity extends AppCompatActivity { + RecyclerView mRecyclerView; + + RecyclerView.LayoutManager mLayoutManager; + + FilesAdapter mAdapter; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_file_list); + + mAdapter = new FilesAdapter(); + + mRecyclerView = (RecyclerView) findViewById(R.id.rvListFiles); + mLayoutManager = new LinearLayoutManager(this); + + assert mRecyclerView != null; + mRecyclerView.setLayoutManager(mLayoutManager); + mRecyclerView.setHasFixedSize(true); + mRecyclerView.setAdapter(mAdapter); + + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) { + mRecyclerView.addItemDecoration(new VerticalSpaceDecorationHelper(this)); + } + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.menu_file_chooser, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + int id = item.getItemId(); + + if (id == R.id.mi_directory_up) { + mAdapter.levelUp(); + } + return super.onOptionsItemSelected(item); + } + + class FilesAdapter extends RecyclerView.Adapter { + ArrayList fileList; + String path; + + FilesAdapter() { + path = Environment.getExternalStorageDirectory().getPath(); + setFileList(); + } + + void levelDown(String next) { + path = path + File.separator + next; + setFileList(); + } + + void levelUp() { + path = path.substring(0, path.lastIndexOf("/")); + setFileList(); + } + + void setFileList() { + fileList = new ArrayList<>(); + File dir = new File(path); + if (!dir.canRead()) { + setTitle("(inaccessible)"); + } + if (dir.isDirectory()) { + String[] list = dir.list(); + if (list != null) { + for (String file : list) { + if (!file.startsWith(".")) { + fileList.add(file); + } + } + } + } else { + selectedLevel(); + } + notifyDataSetChanged(); + } + + void selectedLevel() { + Intent dataRec = new Intent(); + dataRec.putExtra("filepath", path); + setResult(RESULT_OK, dataRec); + finish(); + } + + @Override + public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + final View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_row_files, parent, false); + return new ViewHolder(view); + } + + @Override + public void onBindViewHolder(ViewHolder holder, int position) { + holder.tvDirPath.setText(fileList.get(position)); + } + + @Override + public int getItemCount() { + return fileList.size(); + } + + class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { + TextView tvDirPath; + + ViewHolder(View view) { + super(view); + this.tvDirPath = (TextView) view.findViewById(R.id.tvFileNameOrPath); + view.setOnClickListener(this); + } + + @Override + public void onClick(View view) { + levelDown(tvDirPath.getText().toString()); + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sidzi/circleofmusic/ui/MainActivity.java b/app/src/main/java/com/sidzi/circleofmusic/ui/MainActivity.java index 661a6e1..8ceb92e 100644 --- a/app/src/main/java/com/sidzi/circleofmusic/ui/MainActivity.java +++ b/app/src/main/java/com/sidzi/circleofmusic/ui/MainActivity.java @@ -3,6 +3,7 @@ import android.Manifest; import android.content.ComponentName; import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; @@ -15,20 +16,22 @@ import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; import android.support.v4.content.ContextCompat; +import android.support.v4.content.LocalBroadcastManager; import android.support.v4.view.ViewPager; +import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.SearchView; import android.support.v7.widget.Toolbar; +import android.text.InputType; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.EditText; -import android.widget.FrameLayout; -import android.widget.ImageButton; +import android.widget.LinearLayout; import com.android.volley.Request; import com.android.volley.RequestQueue; @@ -39,23 +42,24 @@ import com.rollbar.android.Rollbar; import com.sidzi.circleofmusic.BuildConfig; import com.sidzi.circleofmusic.R; -import com.sidzi.circleofmusic.adapters.ChatAdapter; import com.sidzi.circleofmusic.adapters.PotmAdapter; import com.sidzi.circleofmusic.adapters.TracksAdapter; -import com.sidzi.circleofmusic.ai.Trebie; import com.sidzi.circleofmusic.config; -import com.sidzi.circleofmusic.helpers.AudioEventHandler; import com.sidzi.circleofmusic.helpers.BucketSaver; import com.sidzi.circleofmusic.helpers.DatabaseSynchronization; import com.sidzi.circleofmusic.helpers.LocalMusicLoader; -import com.sidzi.circleofmusic.helpers.MediaButtonHandler; +import com.sidzi.circleofmusic.helpers.MusicServiceConnection; import com.sidzi.circleofmusic.helpers.VerticalSpaceDecorationHelper; +import com.sidzi.circleofmusic.recievers.MediaButtonHandler; +import com.sidzi.circleofmusic.recievers.MusicPlayerViewHandler; +import com.sidzi.circleofmusic.services.MusicPlayerService; import org.json.JSONException; import org.json.JSONObject; public class MainActivity extends AppCompatActivity { - private AudioEventHandler mAudioEventHandler; + + public MusicServiceConnection mMusicServiceConnection; /** * The {@link android.support.v4.view.PagerAdapter} that will provide * fragments for each of the sections. We use a @@ -71,12 +75,13 @@ public class MainActivity extends AppCompatActivity { */ private ViewPager mViewPager; private SearchView mSearchView; + private MusicPlayerViewHandler mMusicPlayerViewHandler; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // TODO remove key before commit - Rollbar.init(this, config.rollbar_key, "production"); + Rollbar.init(this, config.rollbar_key, "release"); setTheme(R.style.AppTheme_NoActionBar); setContentView(R.layout.activity_main); @@ -110,12 +115,27 @@ public void onErrorResponse(VolleyError error) { }); requestQueue.add(eosCheck); - mAudioEventHandler = new AudioEventHandler(); - registerReceiver(mAudioEventHandler, new IntentFilter("com.sidzi.circleofmusic.PLAY_TRACK")); + + IntentFilter intentFilter = new IntentFilter(); + intentFilter.addAction(MusicPlayerService.ACTION_UPDATE_METADATA); + intentFilter.addAction(MusicPlayerService.ACTION_PAUSE); + intentFilter.addAction(MusicPlayerService.ACTION_PLAY); + intentFilter.addAction(MusicPlayerService.ACTION_CLOSE); + + + Intent intent = new Intent(this, MusicPlayerService.class); + if (MusicPlayerService.PLAYING_TRACK == null) + startService(intent); + mMusicServiceConnection = new MusicServiceConnection(this); + bindService(intent, mMusicServiceConnection, BIND_AUTO_CREATE); + + mMusicPlayerViewHandler = new MusicPlayerViewHandler(this); + LocalBroadcastManager.getInstance(this).registerReceiver(mMusicPlayerViewHandler, intentFilter); /* Handles headphone button click */ + AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); ComponentName componentName = new ComponentName(getPackageName(), MediaButtonHandler.class.getName()); audioManager.registerMediaButtonEventReceiver(componentName); @@ -132,7 +152,7 @@ public void onErrorResponse(VolleyError error) { TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs); tabLayout.setupWithViewPager(mViewPager); - final FrameLayout fl = (FrameLayout) findViewById(R.id.flPlayer); + final LinearLayout fl = (LinearLayout) findViewById(R.id.llPlayer); mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { @@ -141,15 +161,8 @@ public void onPageScrolled(int position, float positionOffset, int positionOffse @Override public void onPageSelected(int position) { - if (position == 2) { - fl.setVisibility(View.GONE); - } else { - if (fl.getVisibility() != View.VISIBLE) { - fl.setVisibility(View.VISIBLE); - } - if (position == 1) { - mSectionsPagerAdapter.notifyDataSetChanged(); - } + if (position >= 1) { + mSectionsPagerAdapter.notifyDataSetChanged(); } } @@ -182,7 +195,6 @@ public boolean onQueryTextChange(String newText) { @Override public boolean onCreateOptionsMenu(final Menu menu) { - getMenuInflater().inflate(R.menu.menu_home, menu); return super.onCreateOptionsMenu(menu); } @@ -200,6 +212,32 @@ public boolean onOptionsItemSelected(MenuItem item) { tabLayout.setVisibility(View.INVISIBLE); } break; + case R.id.alarm: + Intent intent = new Intent(this, AlarmSettingActivity.class); + startActivity(intent); + break; + case R.id.sleepTimer: + AlertDialog.Builder builder = new AlertDialog.Builder(this); + final EditText editText = new EditText(this); + editText.setInputType(InputType.TYPE_CLASS_NUMBER); + builder.setTitle("# of songs till sleep") + .setView(editText) + .setPositiveButton("set", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + mMusicServiceConnection.getmMusicPlayerService().setSongsTillSleep(Integer.parseInt(((editText.getText().toString())))); + dialogInterface.dismiss(); + } + }); + builder.create().show(); + break; + case R.id.exit: + mMusicServiceConnection.getmMusicPlayerService().onDestroy(); + unbindService(mMusicServiceConnection); + stopService(new Intent(this, MusicPlayerService.class)); + LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(MusicPlayerService.ACTION_CLOSE)); + finish(); + break; } return super.onOptionsItemSelected(item); } @@ -213,18 +251,9 @@ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permis @Override protected void onDestroy() { try { - unregisterReceiver(mAudioEventHandler); BucketSaver bucketSaver = new BucketSaver(this); bucketSaver.saveFile(); - if (AudioEventHandler.mMediaPlayer.isPlaying()) { -// Add background service here - AudioEventHandler.mMediaPlayer.stop(); - } - AudioEventHandler.mTrackProgressObserver.stop(); - AudioEventHandler.mMediaPlayer.reset(); - AudioEventHandler.mMediaPlayer.release(); - AudioEventHandler.mMediaPlayer = null; - AudioEventHandler.mNotificationManager.cancelAll(); + unbindService(mMusicServiceConnection); } catch (IllegalArgumentException | NullPointerException e) { e.printStackTrace(); } @@ -284,35 +313,35 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, final PotmAdapter potmAdapter = new PotmAdapter(getContext()); mRecyclerView.setAdapter(potmAdapter); break; +// case 3: +// homeView = inflater.inflate(R.layout.fragment_chat_bot, container, false); +// final RecyclerView chatRecyclerView = (RecyclerView) homeView.findViewById(R.id.rvChatConsole); +// final Trebie mTrebie = new Trebie(getContext()); +// final ChatAdapter chatAdapter = new ChatAdapter(); +// final LinearLayoutManager chatLayoutManager = new LinearLayoutManager(getContext()); +// mTrebie.setmChatAdapter(chatAdapter); +// mTrebie.setmRecyclerView(chatRecyclerView); +// chatLayoutManager.setStackFromEnd(true); +// chatRecyclerView.setAdapter(chatAdapter); +// chatRecyclerView.setLayoutManager(chatLayoutManager); +// ImageButton ibSend = (ImageButton) homeView.findViewById(R.id.ibSendMessage); +// final EditText etChatMessage = (EditText) homeView.findViewById(R.id.etChatMessage); +// etChatMessage.setHint("Say \"help me\" to Trebie to get started"); +// ibSend.setOnClickListener(new View.OnClickListener() { +// @Override +// public void onClick(View view) { +// etChatMessage.setHint(""); +// String message = etChatMessage.getText().toString(); +// if (!message.equals("")) { +// chatAdapter.addMessage(message, true); +// chatRecyclerView.smoothScrollToPosition(chatAdapter.getItemCount()); +// etChatMessage.setText(""); +// mTrebie.converse(message, null); +// } +// } +// }); +// break; case 3: - homeView = inflater.inflate(R.layout.fragment_chat_bot, container, false); - final RecyclerView chatRecyclerView = (RecyclerView) homeView.findViewById(R.id.rvChatConsole); - final Trebie mTrebie = new Trebie(getContext()); - final ChatAdapter chatAdapter = new ChatAdapter(); - final LinearLayoutManager chatLayoutManager = new LinearLayoutManager(getContext()); - mTrebie.setmChatAdapter(chatAdapter); - mTrebie.setmRecyclerView(chatRecyclerView); - chatLayoutManager.setStackFromEnd(true); - chatRecyclerView.setAdapter(chatAdapter); - chatRecyclerView.setLayoutManager(chatLayoutManager); - ImageButton ibSend = (ImageButton) homeView.findViewById(R.id.ibSendMessage); - final EditText etChatMessage = (EditText) homeView.findViewById(R.id.etChatMessage); - etChatMessage.setHint("Say \"help me\" to Trebie to get started"); - ibSend.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - etChatMessage.setHint(""); - String message = etChatMessage.getText().toString(); - if (!message.equals("")) { - chatAdapter.addMessage(message, true); - chatRecyclerView.smoothScrollToPosition(chatAdapter.getItemCount()); - etChatMessage.setText(""); - mTrebie.converse(message, null); - } - } - }); - break; - case 4: TracksAdapter tracksAdapter2 = new TracksAdapter(getContext()); tracksAdapter2.getBucketedTracks(); mRecyclerView.setAdapter(tracksAdapter2); @@ -341,8 +370,8 @@ public Fragment getItem(int position) { @Override public int getCount() { - // Show 4 total pages. - return 4; + // Show 3 total pages. + return 3; } @Override @@ -352,9 +381,9 @@ public CharSequence getPageTitle(int position) { return "Local"; case 1: return "POTM"; +// case 2: +// return "Trebie"; case 2: - return "Trebie"; - case 3: return "Bucket"; } return null; diff --git a/app/src/main/java/com/sidzi/circleofmusic/views/MusicPlaybackPanel.java b/app/src/main/java/com/sidzi/circleofmusic/views/MusicPlaybackPanel.java new file mode 100644 index 0000000..b060e11 --- /dev/null +++ b/app/src/main/java/com/sidzi/circleofmusic/views/MusicPlaybackPanel.java @@ -0,0 +1,97 @@ +//package com.sidzi.circleofmusic.views; +// +// +//import android.content.Context; +//import android.util.AttributeSet; +//import android.view.MotionEvent; +//import android.widget.FrameLayout; +//import android.widget.ImageButton; +//import android.widget.ProgressBar; +//import android.widget.TextView; +// +//import com.sidzi.circleofmusic.R; +// +//public class MusicPlaybackPanel extends FrameLayout { +// +// private TextView tvPlayingTrackName = null; +// private TextView tvPlayingArtistName = null; +// private ImageButton ibPlay = null; +// private ImageButton ibAddToBucket = null; +// private ImageButton ibPlayNext = null; +// private ProgressBar pbTrackPlay = null; +// private Context mContext; +// +// public MusicPlaybackPanel(Context context) { +// super(context); +// mContext = context; +// inflate(context, R.layout.playback_panel, this); +// init(); +// } +// +// public MusicPlaybackPanel(Context context, AttributeSet attrs) { +// super(context, attrs); +// inflate(context, R.layout.playback_panel, this); +// init(); +// } +// +// +// void init() { +// tvPlayingTrackName = (TextView) findViewById(R.id.tvPlayingTrackName); +// tvPlayingArtistName = (TextView) findViewById(R.id.tvPlayingTrackArtist); +// ibPlay = (ImageButton) findViewById(R.id.ibPlayPause); +// ibAddToBucket = (ImageButton) findViewById(R.id.ibAddToBucket); +// ibPlayNext = (ImageButton) findViewById(R.id.ibPlayNext); +// pbTrackPlay = (ProgressBar) findViewById(R.id.pbTrackPlay); +// } +// +// @Override +// public boolean onTouchEvent(MotionEvent event) { +// return false; +// } +// +//// void setup() { +//// ibPlay.setOnClickListener(new View.OnClickListener() { +//// @Override +//// public void onClick(final View v) { +//// if (mMediaPlayer.isPlaying()) { +//// mMediaPlayer.pause(); +//// } else { +//// mMediaPlayer.start(); +//// } +//// } +//// }); +//// ibAddToBucket.setOnClickListener(new View.OnClickListener() { +//// @Override +//// public void onClick(View v) { +//// if (mMediaPlayer != null) { +//// Utils.bucketOps(MusicPlayerService.PLAYING_TRACK_PATH, !(Boolean) ibAddToBucket.getTag(), mContext); +//// if (!(Boolean) ibAddToBucket.getTag()) { +//// ((ImageButton) v).setImageResource(R.drawable.ic_track_bucket_added); +//// Toast.makeText(mContext, "Added to bucket", Toast.LENGTH_SHORT).show(); +//// } else { +//// ((ImageButton) v).setImageResource(R.drawable.ic_track_bucket_add); +//// } +//// ibAddToBucket.setTag(!(Boolean) ibAddToBucket.getTag()); +//// } +//// } +//// }); +//// ibPlayNext.setOnClickListener(new View.OnClickListener() { +//// @Override +//// public void onClick(View view) { +//// MusicPlayerService.next(); +//// } +//// }); +//// } +//// +//// public void updateViews() { +//// ibPlay.setImageResource(R.drawable.ic_track_stop); +//// tvPlayingTrackName.setText(MusicPlayerService.PLAYING_TRACK.getName()); +//// tvPlayingArtistName.setText(MusicPlayerService.PLAYING_TRACK.getAlbum()); +//// if (!MusicPlayerService.PLAYING_TRACK.getBucket()) { +//// ibAddToBucket.setImageResource(R.drawable.ic_track_bucket_add); +//// } else { +//// ibAddToBucket.setImageResource(R.drawable.ic_track_bucket_added); +//// } +//// ibAddToBucket.setTag(MusicPlayerService.PLAYING_TRACK.getBucket()); +//// } +//} diff --git a/app/src/main/res/drawable-hdpi/ic_directory_up.png b/app/src/main/res/drawable-hdpi/ic_directory_up.png new file mode 100644 index 0000000..64a1835 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_directory_up.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_directory_up.png b/app/src/main/res/drawable-mdpi/ic_directory_up.png new file mode 100644 index 0000000..acd8b1d Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_directory_up.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_directory_up.png b/app/src/main/res/drawable-xhdpi/ic_directory_up.png new file mode 100644 index 0000000..2596971 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_directory_up.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_directory_up.png b/app/src/main/res/drawable-xxhdpi/ic_directory_up.png new file mode 100644 index 0000000..08ab651 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_directory_up.png differ diff --git a/app/src/main/res/drawable/splash_logo.png b/app/src/main/res/drawable/splash_logo.png index 5c895fd..570c59f 100644 Binary files a/app/src/main/res/drawable/splash_logo.png and b/app/src/main/res/drawable/splash_logo.png differ diff --git a/app/src/main/res/layout/activity_alarm.xml b/app/src/main/res/layout/activity_alarm.xml new file mode 100644 index 0000000..e1c2f68 --- /dev/null +++ b/app/src/main/res/layout/activity_alarm.xml @@ -0,0 +1,50 @@ + + + + + + + + + + +