diff --git a/.idea/Mear.iml b/.idea/Mear.iml index cd61b1c..0fbbc63 100644 --- a/.idea/Mear.iml +++ b/.idea/Mear.iml @@ -1,5 +1,13 @@ + + + + + + diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser index ec56d95..e1171e0 100644 Binary files a/.idea/caches/build_file_checksums.ser and b/.idea/caches/build_file_checksums.ser differ diff --git a/.idea/render.experimental.xml b/.idea/render.experimental.xml new file mode 100644 index 0000000..8ec256a --- /dev/null +++ b/.idea/render.experimental.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 64016f7..3da38be 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,32 +1,38 @@ + package="com.example.mear"> - + + android:allowBackup="true" + android:icon="@mipmap/ic_launcher" + android:label="@string/app_name" + android:roundIcon="@mipmap/ic_launcher_round" + android:supportsRtl="true" + android:theme="@style/AppTheme"> + android:name=".activities.SettingsActivity" + android:label="@string/title_activity_settings" + android:parentActivityName=".activities.MainActivity" + android:theme="@style/AppTheme.NoActionBar"> + android:name="android.support.PARENT_ACTIVITY" + android:value="com.example.mear.activities.MainActivity" /> + android:name=".activities.fdh" + android:label="@string/title_activity_settings" + android:screenOrientation="portrait"> + - + - + diff --git a/app/src/main/java/com/example/mear/activities/MainActivity.kt b/app/src/main/java/com/example/mear/activities/MainActivity.kt index 6f0ebb6..ef8a676 100644 --- a/app/src/main/java/com/example/mear/activities/MainActivity.kt +++ b/app/src/main/java/com/example/mear/activities/MainActivity.kt @@ -1,29 +1,28 @@ package com.example.mear.activities +import android.graphics.Color +import android.content.Intent import android.graphics.BitmapFactory import android.media.MediaPlayer import android.media.MediaMetadataRetriever import android.os.Bundle -import android.os.Environment import android.support.v7.app.AppCompatActivity -import android.text.format.Time -import com.example.mear.R import java.lang.Exception +import java.util.concurrent.TimeUnit import kotlinx.android.synthetic.main.activity_main.* -import kotlinx.android.synthetic.main.content_main.* -import kotlin.io.* -import kotlin.random.Random - -import com.example.mear.management.MusicFiles -import com.example.mear.management.TrackManager -import com.example.mear.repositories.TrackRepository import kotlinx.android.synthetic.main.fragment_play_controls.* import kotlinx.android.synthetic.main.fragment_track_cover.* import kotlinx.android.synthetic.main.fragment_track_details.* import kotlinx.android.synthetic.main.fragment_track_elapsing.* import kotlinx.android.synthetic.main.fragment_track_flow.* -import java.util.concurrent.TimeUnit +import kotlin.io.* +import kotlin.random.Random + +import com.example.mear.R +import com.example.mear.repositories.TrackRepository +import org.jetbrains.anko.image + class MainActivity : AppCompatActivity() { @@ -32,8 +31,6 @@ class MainActivity : AppCompatActivity() { setContentView(R.layout.activity_main) setSupportActionBar(toolbar) - //loadTracks(loadSongPaths()) - initialize() } @@ -59,6 +56,18 @@ class MainActivity : AppCompatActivity() { ShuffleTracks.setOnClickListener { toggleShuffle() } + SettingsLink.setOnClickListener { + val intent = Intent(this, SettingsActivity::class.java) + try { + + + startActivity(intent) + } + catch (ex: Exception) { + val exMsg = ex.message + println(exMsg) + } + } } private fun initializeCompletionListener() { trackPlayer!!.setOnCompletionListener { @@ -100,10 +109,10 @@ class MainActivity : AppCompatActivity() { try { if (!trackPlayer!!.isPlaying) { trackPlayer!!.start() - configureTrackDisplay() } else { trackPlayer!!.pause() } + configureTrackDisplay() } catch (ex: Exception) { val exMsg = ex.message @@ -153,39 +162,53 @@ class MainActivity : AppCompatActivity() { PreviousTrack.isEnabled = true } private fun configureTrackDisplay() { + configurePlayControlsDisplay() val currTrack = TrackRepository(this).getTrack(currentSong!!) val trackTitle = currTrack.title val artistTitle = currTrack.artist val albumTitle = currTrack.album - var trackDuration = currTrack.length + val trackDuration = currTrack.length var trackCover: ByteArray? = null val dur = String.format("%02d:%02d", TimeUnit.SECONDS.toMinutes(trackDuration.toLong()), (trackDuration % 60) ) - var mmr = MediaMetadataRetriever() + val mmr = MediaMetadataRetriever() mmr.setDataSource(currTrack.songPath) if (mmr.embeddedPicture != null) { trackCover = mmr.embeddedPicture } - TrackTitle.setText(null) - ArtistTitle.setText(null) - AlbumTitle.setText(null) - CurrentPosition.setText(null) + TrackTitle.text = null + ArtistTitle.text = null + AlbumTitle.text = null + CurrentPosition.text = null TrackCover.setImageBitmap(null) - TrackTitle.setText(trackTitle) - ArtistTitle.setText(artistTitle) - AlbumTitle.setText(albumTitle) - TrackDuration.setText(dur) + TrackTitle.text = trackTitle + ArtistTitle.text = artistTitle + AlbumTitle.text = albumTitle + TrackDuration.text = dur if (trackCover != null) { val songImage = BitmapFactory .decodeByteArray(trackCover, 0, trackCover.size) TrackCover.setImageBitmap(songImage) } } + private fun configurePlayControlsDisplay() { + PlayTrack.background = null + PlayTrack.colorFilter = null + + if (!trackPlayer!!.isPlaying) { + PlayTrack.setImageResource(android.R.drawable.ic_media_pause) + PlayTrack.setColorFilter(Color.RED) + } + else { + PlayTrack.setImageResource(android.R.drawable.ic_media_play) + PlayTrack.setColorFilter(Color.GREEN) + } + } private fun fetchSongIndex(playType: PlayTypes): Int { var songIndex: Int? = null @@ -227,33 +250,11 @@ class MainActivity : AppCompatActivity() { return songIndex!! } - private fun loadSongPaths(): MutableList { - val demoPath = Environment.getExternalStorageDirectory() - val mfPaths = MusicFiles(demoPath) - mfPaths.loadAllMusicPaths() - val allSongs = mfPaths.allSongs - - return allSongs!! - } - private fun loadTracks(allSongs: MutableList) { - try { - val trackMgr = TrackManager(allSongs) - songCount = trackMgr.configureTracks(this) - - songCount = TrackRepository(this).getSongCount() - - currentSong = fetchSongIndex(PlayTypes.PlaySong) - } - catch (ex: Exception) { - val exMsg = ex.message - } - } - private var trackPlayer: MediaPlayer? = null private var currentSong: Int? = null - private var playerInitialized: Boolean? = null - private var shuffleOn: Boolean? = null + private var playerInitialized: Boolean? = false + private var shuffleOn: Boolean? = false private var songCount: Int? = null private enum class PlayTypes { diff --git a/app/src/main/java/com/example/mear/activities/SettingsActivity.kt b/app/src/main/java/com/example/mear/activities/SettingsActivity.kt index fdc6bb2..773d9b2 100644 --- a/app/src/main/java/com/example/mear/activities/SettingsActivity.kt +++ b/app/src/main/java/com/example/mear/activities/SettingsActivity.kt @@ -1,255 +1,56 @@ package com.example.mear.activities -import android.annotation.TargetApi -import android.content.Context -import android.content.Intent -import android.content.res.Configuration -import android.media.RingtoneManager -import android.net.Uri -import android.os.Build import android.os.Bundle -import android.preference.ListPreference -import android.preference.Preference -import android.preference.PreferenceActivity -import android.preference.PreferenceFragment -import android.preference.PreferenceManager -import android.preference.RingtonePreference -import android.text.TextUtils -import android.view.MenuItem -import android.support.v4.app.NavUtils -import com.example.mear.AppCompatPreferenceActivity -import com.example.mear.R +import android.os.Environment +import android.support.v7.app.AppCompatActivity; -/** - * A [PreferenceActivity] that presents a set of application settings. On - * handset devices, settings are presented as a single list. On tablets, - * settings are split by category, with category headers shown to the left of - * the list of settings. - * - * See [Android Design: Settings](http://developer.android.com/design/patterns/settings.html) - * for design guidelines and the [Settings API Guide](http://developer.android.com/guide/topics/ui/settings.html) - * for more information on developing a Settings UI. - */ -class SettingsActivity : AppCompatPreferenceActivity() { +import java.lang.Exception +import kotlinx.android.synthetic.main.activity_settings.* +import kotlinx.android.synthetic.main.content_settings.* + +import com.example.mear.R +import com.example.mear.management.MusicFiles +import com.example.mear.management.TrackManager +import com.example.mear.repositories.TrackRepository + + + +class SettingsActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setupActionBar() - } + setContentView(R.layout.activity_settings) + setSupportActionBar(toolbar) + + RefreshLibrary.setOnClickListener { + updateLibrary() + } - /** - * Set up the [android.app.ActionBar], if the API is available. - */ - private fun setupActionBar() { supportActionBar?.setDisplayHomeAsUpEnabled(true) } - override fun onMenuItemSelected(featureId: Int, item: MenuItem): Boolean { - val id = item.itemId - if (id == android.R.id.home) { - if (!super.onMenuItemSelected(featureId, item)) { - NavUtils.navigateUpFromSameTask(this) - } - return true + + private fun loadSongPaths(): MutableList { + val demoPath = Environment.getExternalStorageDirectory() + val mfPaths = MusicFiles(demoPath) + mfPaths.loadAllMusicPaths() + val allSongs = mfPaths.allSongs + + return allSongs!! + } + private fun loadTracks(allSongs: MutableList) { + try { + TrackRepository(this).delete() + val trackMgr = TrackManager(allSongs) } - return super.onMenuItemSelected(featureId, item) - } - - /** - * {@inheritDoc} - */ - override fun onIsMultiPane(): Boolean { - return isXLargeTablet(this) - } - - /** - * {@inheritDoc} - */ - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - override fun onBuildHeaders(target: List) { - loadHeadersFromResource(R.xml.pref_headers, target) - } - - /** - * This method stops fragment injection in malicious applications. - * Make sure to deny any unknown fragments here. - */ - override fun isValidFragment(fragmentName: String): Boolean { - return PreferenceFragment::class.java.name == fragmentName - || GeneralPreferenceFragment::class.java.name == fragmentName - || DataSyncPreferenceFragment::class.java.name == fragmentName - || NotificationPreferenceFragment::class.java.name == fragmentName - } - - /** - * This fragment shows general preferences only. It is used when the - * activity is showing a two-pane settings UI. - */ - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - class GeneralPreferenceFragment : PreferenceFragment() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - addPreferencesFromResource(R.xml.pref_general) - setHasOptionsMenu(true) - - // Bind the summaries of EditText/List/Dialog/Ringtone preferences - // to their values. When their values change, their summaries are - // updated to reflect the new value, per the Android Design - // guidelines. - bindPreferenceSummaryToValue(findPreference("example_text")) - bindPreferenceSummaryToValue(findPreference("example_list")) - } - - override fun onOptionsItemSelected(item: MenuItem): Boolean { - val id = item.itemId - if (id == android.R.id.home) { - startActivity(Intent(activity, SettingsActivity::class.java)) - return true - } - return super.onOptionsItemSelected(item) + catch (ex: Exception) { + val exMsg = ex.message } } - /** - * This fragment shows notification preferences only. It is used when the - * activity is showing a two-pane settings UI. - */ - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - class NotificationPreferenceFragment : PreferenceFragment() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - addPreferencesFromResource(R.xml.pref_notification) - setHasOptionsMenu(true) - // Bind the summaries of EditText/List/Dialog/Ringtone preferences - // to their values. When their values change, their summaries are - // updated to reflect the new value, per the Android Design - // guidelines. - bindPreferenceSummaryToValue(findPreference("notifications_new_message_ringtone")) - } - override fun onOptionsItemSelected(item: MenuItem): Boolean { - val id = item.itemId - if (id == android.R.id.home) { - startActivity(Intent(activity, SettingsActivity::class.java)) - return true - } - return super.onOptionsItemSelected(item) - } - } - - /** - * This fragment shows data and sync preferences only. It is used when the - * activity is showing a two-pane settings UI. - */ - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - class DataSyncPreferenceFragment : PreferenceFragment() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - addPreferencesFromResource(R.xml.pref_data_sync) - setHasOptionsMenu(true) - - // Bind the summaries of EditText/List/Dialog/Ringtone preferences - // to their values. When their values change, their summaries are - // updated to reflect the new value, per the Android Design - // guidelines. - bindPreferenceSummaryToValue(findPreference("sync_frequency")) - } - - override fun onOptionsItemSelected(item: MenuItem): Boolean { - val id = item.itemId - if (id == android.R.id.home) { - startActivity(Intent(activity, SettingsActivity::class.java)) - return true - } - return super.onOptionsItemSelected(item) - } - } - - companion object { - - /** - * A preference value change listener that updates the preference's summary - * to reflect its new value. - */ - private val sBindPreferenceSummaryToValueListener = Preference.OnPreferenceChangeListener { preference, value -> - val stringValue = value.toString() - - if (preference is ListPreference) { - // For list preferences, look up the correct display value in - // the preference's 'entries' list. - val listPreference = preference - val index = listPreference.findIndexOfValue(stringValue) - - // Set the summary to reflect the new value. - preference.setSummary( - if (index >= 0) - listPreference.entries[index] - else - null - ) - - } else if (preference is RingtonePreference) { - // For ringtone preferences, look up the correct display value - // using RingtoneManager. - if (TextUtils.isEmpty(stringValue)) { - // Empty values correspond to 'silent' (no ringtone). - preference.setSummary(R.string.pref_ringtone_silent) - - } else { - val ringtone = RingtoneManager.getRingtone( - preference.getContext(), Uri.parse(stringValue) - ) - - if (ringtone == null) { - // Clear the summary if there was a lookup error. - preference.setSummary(null) - } else { - // Set the summary to reflect the new ringtone display - // name. - val name = ringtone.getTitle(preference.getContext()) - preference.setSummary(name) - } - } - - } else { - // For all other preferences, set the summary to the value's - // simple string representation. - preference.summary = stringValue - } - true - } - - /** - * Helper method to determine if the device has an extra-large screen. For - * example, 10" tablets are extra-large. - */ - private fun isXLargeTablet(context: Context): Boolean { - return context.resources.configuration.screenLayout and Configuration.SCREENLAYOUT_SIZE_MASK >= Configuration.SCREENLAYOUT_SIZE_XLARGE - } - - /** - * Binds a preference's summary to its value. More specifically, when the - * preference's value is changed, its summary (line of text below the - * preference title) is updated to reflect the value. The summary is also - * immediately updated upon calling this method. The exact display format is - * dependent on the type of preference. - - * @see .sBindPreferenceSummaryToValueListener - */ - private fun bindPreferenceSummaryToValue(preference: Preference) { - // Set the listener to watch for value changes. - preference.onPreferenceChangeListener = - sBindPreferenceSummaryToValueListener - - // Trigger the listener immediately with the preference's - // current value. - sBindPreferenceSummaryToValueListener.onPreferenceChange( - preference, - PreferenceManager - .getDefaultSharedPreferences(preference.context) - .getString(preference.key, "") - ) - } + private fun updateLibrary() { + loadTracks(loadSongPaths()) } } diff --git a/app/src/main/java/com/example/mear/management/DatabaseManager.kt b/app/src/main/java/com/example/mear/management/DatabaseManager.kt index 480c1e8..7cafc3c 100644 --- a/app/src/main/java/com/example/mear/management/DatabaseManager.kt +++ b/app/src/main/java/com/example/mear/management/DatabaseManager.kt @@ -42,7 +42,7 @@ class DatabaseManager(ctx: Context): ManagedSQLiteOpenHelper(ctx, "Mear", "TrackId" to INTEGER ) db!!.createTable( - "Settings", true, + "SettingsActivity", true, "Id" to INTEGER + PRIMARY_KEY + UNIQUE, "DarkTheme" to org.jetbrains.anko.db.REAL ) @@ -56,7 +56,7 @@ class DatabaseManager(ctx: Context): ManagedSQLiteOpenHelper(ctx, "Mear", db!!.dropTable("Track") db!!.dropTable("TrackCount") db!!.dropTable("PlayCount") - db!!.dropTable("Settings") + db!!.dropTable("SettingsActivity") } catch (ex: Exception) { diff --git a/app/src/main/java/com/example/mear/management/TrackManager.kt b/app/src/main/java/com/example/mear/management/TrackManager.kt index 569c207..f74b4cb 100644 --- a/app/src/main/java/com/example/mear/management/TrackManager.kt +++ b/app/src/main/java/com/example/mear/management/TrackManager.kt @@ -42,16 +42,6 @@ class TrackManager(var allSongPath: MutableList) { } return id.dec() } - fun dumpToDatabase(ctx: Context) { - TrackRepository(ctx).delete() - for (songData in allTracks!!) { - TrackRepository(ctx).insertTrack(songData) - allTracks!!.removeAt(songData.id ) - } - } - fun deleteTable(ctx: Context) { - TrackRepository(ctx).delete() - } private fun dumpToDatabase(ctx: Context, track: Track) { TrackRepository(ctx).insertTrack(track) PlayCountRepository(ctx).insertPlayCount(track) diff --git a/app/src/main/java/com/example/mear/repositories/SettingRepository.kt b/app/src/main/java/com/example/mear/repositories/SettingRepository.kt index eba889a..81a952a 100644 --- a/app/src/main/java/com/example/mear/repositories/SettingRepository.kt +++ b/app/src/main/java/com/example/mear/repositories/SettingRepository.kt @@ -9,7 +9,7 @@ import com.example.mear.models.Settings class SettingRepository(val context: Context) { fun getSettings(id: Int): Settings = context.database.use { - select("Settings").where("Id = $id") + select("SettingsActivity").where("Id = $id") .parseSingle(object: MapRowParser{ override fun parseRow(columns: Map): Settings { val id = columns.getValue("Id").toString().toInt() @@ -22,20 +22,20 @@ class SettingRepository(val context: Context) { }) } fun insertSettings(settings: Settings) = context.database.use { - insert("Settings", + insert("SettingsActivity", "Id" to settings.id, "DarkTheme" to false) } fun updateSettings(settings: Settings) = context.database.use { - update("Settings", + update("SettingsActivity", "DarkTheme" to settings.darkTheme) .where("Id = {settingId}", "settingId" to settings.id).exec() } fun delete(table: Settings?) = context.database.use { - delete("Settings", whereClause = "id = {$table.id}") + delete("SettingsActivity", whereClause = "id = {$table.id}") } fun delete() = context.database.use { - delete("Settings") + delete("SettingsActivity") } } \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index fd9adb0..3d2b99f 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -8,19 +8,37 @@ tools:context=".activities.MainActivity"> + android:id="@+id/appBarLayout" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:theme="@style/AppTheme.AppBarOverlay"> - + + + android:baselineAligned="false" + app:popupTheme="@style/AppTheme.PopupOverlay" /> + + + - + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_setting.xml b/app/src/main/res/layout/activity_setting.xml deleted file mode 100644 index fed8833..0000000 --- a/app/src/main/res/layout/activity_setting.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml new file mode 100644 index 0000000..93d4f49 --- /dev/null +++ b/app/src/main/res/layout/activity_settings.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/content_main.xml b/app/src/main/res/layout/content_main.xml index afe7534..9d6ee24 100644 --- a/app/src/main/res/layout/content_main.xml +++ b/app/src/main/res/layout/content_main.xml @@ -21,4 +21,5 @@ + \ No newline at end of file diff --git a/app/src/main/res/layout/content_settings.xml b/app/src/main/res/layout/content_settings.xml new file mode 100644 index 0000000..b6fc6ae --- /dev/null +++ b/app/src/main/res/layout/content_settings.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_play_controls.xml b/app/src/main/res/layout/fragment_play_controls.xml index 93fd17c..49c0e4a 100644 --- a/app/src/main/res/layout/fragment_play_controls.xml +++ b/app/src/main/res/layout/fragment_play_controls.xml @@ -5,36 +5,42 @@ android:layout_width="match_parent" android:layout_height="match_parent"> -