commit 25cd89a533c5cf2a14fa4d1e83150df025d13a9d Author: Sebastian Seedorf Date: Sun Dec 6 20:07:03 2020 +0100 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7ea113c --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +.gradle +/local.properties +/.idea/* +/.idea - PC/* +.DS_Store +/build +/captures +.externalNativeBuild +app/release/* diff --git a/GreenMangoSongfinder.iml b/GreenMangoSongfinder.iml new file mode 100644 index 0000000..2a033f2 --- /dev/null +++ b/GreenMangoSongfinder.iml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/app.iml b/app/app.iml new file mode 100644 index 0000000..cdb0f65 --- /dev/null +++ b/app/app.iml @@ -0,0 +1,191 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..23ddcde --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,45 @@ +apply plugin: 'com.android.application' + +apply plugin: 'kotlin-android' + +apply plugin: 'kotlin-android-extensions' + +apply plugin: 'kotlin-kapt' + +android { + compileSdkVersion 28 + defaultConfig { + applicationId "com.example.greenmangosongfinder" + minSdkVersion 21 + targetSdkVersion 28 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation 'androidx.appcompat:appcompat:1.0.2' + implementation 'androidx.core:core-ktx:1.0.2' + implementation 'androidx.constraintlayout:constraintlayout:1.1.3' + implementation 'com.google.android.material:material:1.0.0' + implementation 'com.android.volley:volley:1.1.1' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.0.1' + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.1" + implementation 'androidx.legacy:legacy-support-v4:1.0.0' + implementation 'androidx.recyclerview:recyclerview:1.0.0' + implementation 'xyz.danoz:recyclerviewfastscroller:0.1.3' + testImplementation 'junit:junit:4.12' + androidTestImplementation 'androidx.test:runner:1.2.0' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' + implementation 'androidx.room:room-runtime:2.1.0' + kapt 'androidx.room:room-compiler:2.1.0' +} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/app/src/androidTest/java/com/example/greenmangosongfinder/ExampleInstrumentedTest.kt b/app/src/androidTest/java/com/example/greenmangosongfinder/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..1b6c947 --- /dev/null +++ b/app/src/androidTest/java/com/example/greenmangosongfinder/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package com.example.greenmangosongfinder + +import androidx.test.InstrumentationRegistry +import androidx.test.runner.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getTargetContext() + assertEquals("com.example.greenmangosongfinder", appContext.packageName) + } +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..ff94e8a --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/example/greenmangosongfinder/ColorGroupSectionTitleIndicator.kt b/app/src/main/java/com/example/greenmangosongfinder/ColorGroupSectionTitleIndicator.kt new file mode 100644 index 0000000..fa839ce --- /dev/null +++ b/app/src/main/java/com/example/greenmangosongfinder/ColorGroupSectionTitleIndicator.kt @@ -0,0 +1,24 @@ +package com.example.greenmangosongfinder + +import android.content.Context +import android.util.AttributeSet +import xyz.danoz.recyclerviewfastscroller.sectionindicator.title.SectionTitleIndicator + + +/** + * Indicator for sections of type [ColorGroup] + */ +class ColorGroupSectionTitleIndicator : SectionTitleIndicator { + + constructor(context: Context) : super(context) {} + + constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {} + + constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {} + + override fun setSection(caption: String) { + // Example of using a single character + setTitleText(caption) + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/example/greenmangosongfinder/EntryRecyclerViewAdapter.kt b/app/src/main/java/com/example/greenmangosongfinder/EntryRecyclerViewAdapter.kt new file mode 100644 index 0000000..aa56cd2 --- /dev/null +++ b/app/src/main/java/com/example/greenmangosongfinder/EntryRecyclerViewAdapter.kt @@ -0,0 +1,90 @@ +package com.example.greenmangosongfinder + +import androidx.recyclerview.widget.RecyclerView +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.SectionIndexer +import android.widget.TextView + + +import com.example.greenmangosongfinder.SongFragment.OnListFragmentInteractionListener +import com.example.greenmangosongfinder.bin.database.Entry + +import kotlinx.android.synthetic.main.fragment_song.view.* +import java.lang.Math.max +import java.lang.Math.min + +/** + * [RecyclerView.Adapter] that can display a [Entry] and makes a call to the + * specified [OnListFragmentInteractionListener]. + * TODO: Replace the implementation with code for your data type. + */ +class EntryRecyclerViewAdapter ( + private val mValues: List, + private val mListener: OnListFragmentInteractionListener? +) : RecyclerView.Adapter(), SectionIndexer { + private val TAG = "EntryRecyclerViewAdapte" + + private val mOnClickListener: View.OnClickListener + + init { + mOnClickListener = View.OnClickListener { v -> + val item = v.tag as Entry + // Notify the active callbacks interface (the activity, if the fragment is attached to + // one) that an item has been selected. + mListener?.onItemSelected(item) + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + val view = LayoutInflater.from(parent.context) + .inflate(R.layout.fragment_song, parent, false) + return ViewHolder(view) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + val item = mValues[position] + holder.mTitle.text = "${item.artist} - ${item.title}" + holder.mContentView.text = item.code + holder.mDate.text = item.language + + with(holder.mView) { + tag = item + setOnClickListener(mOnClickListener) + } + } + + override fun getItemCount(): Int = mValues.size + + override fun getSections(): Array { + return with("ABCDEFGHIJKLMNOPQRSTUVWXYZ") { + split("").subList(1, length+1).toTypedArray() + } + } + + override fun getSectionForPosition(position: Int): Int { + val idx = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".indexOf(mValues[min(position, itemCount - 1)].artist[0]) + return max(0, min(idx, "ABCDEFGHIJKLMNOPQRSTUVWXYZ".length-1)) + } + + override fun getPositionForSection(sectionIndex: Int): Int { + val alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + for ((idx, value) in mValues.withIndex()) { + if (value.artist[0] == alphabet[sectionIndex]) { + return idx + } + } + return 0 + } + + inner class ViewHolder(val mView: View) : RecyclerView.ViewHolder(mView) { + val mTitle: TextView = mView.title + val mContentView: TextView = mView.reporter + val mDate: TextView = mView.date + + override fun toString(): String { + return super.toString() + " '" + mContentView.text + "'" + } + } +} diff --git a/app/src/main/java/com/example/greenmangosongfinder/MainActivity.kt b/app/src/main/java/com/example/greenmangosongfinder/MainActivity.kt new file mode 100644 index 0000000..2bcc007 --- /dev/null +++ b/app/src/main/java/com/example/greenmangosongfinder/MainActivity.kt @@ -0,0 +1,73 @@ +package com.example.greenmangosongfinder + +import android.os.Bundle +import android.util.Log +import android.view.Menu +import android.view.MenuItem +import androidx.appcompat.app.AppCompatActivity +import com.example.greenmangosongfinder.bin.Download +import com.example.greenmangosongfinder.bin.database.AppDatabase +import com.example.greenmangosongfinder.bin.database.Entry +import com.google.android.material.snackbar.Snackbar +import kotlinx.android.synthetic.main.activity_main.* +import kotlinx.android.synthetic.main.content_main.* +import xyz.danoz.recyclerviewfastscroller.sectionindicator.title.SectionTitleIndicator + +class MainActivity : AppCompatActivity(), SongFragment.OnListFragmentInteractionListener { + private val TAG = "MainActivity" + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + setSupportActionBar(toolbar) + + fab.setOnClickListener { view -> + Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) + .setAction("Action", null).show() + } + + list.layoutManager = androidx.recyclerview.widget.LinearLayoutManager(applicationContext) + val db = AppDatabase.getAppDatabase(applicationContext) + list.adapter = EntryRecyclerViewAdapter(db.entryDao().getAll(), this) + fast_scroller.setRecyclerView(list) + list.addOnScrollListener(fast_scroller.onScrollListener) + fast_scroller.sectionIndicator = fast_scroller_section_title_indicator + } + + override fun onItemSelected(item: Entry) { + Log.d(TAG, "Clicked on entry: $item") + Snackbar.make(fab, "Entry: $item", Snackbar.LENGTH_LONG) + } + + override fun onStart() { + super.onStart() + val db = AppDatabase.getAppDatabase(this) + Log.d(TAG, db.entryDao().getCount().toString()) + } + + override fun onCreateOptionsMenu(menu: Menu): Boolean { + // Inflate the menu; this adds items to the action bar if it is present. + menuInflater.inflate(R.menu.menu_main, menu) + return true + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + // Handle action bar item clicks here. The action bar will + // automatically handle clicks on the Home/Up button, so long + // as you specify a parent activity in AndroidManifest.xml. + return when (item.itemId) { + R.id.action_refresh -> { + val download = Download(this) + download.refreshList { + //findViewById('main').setText(it) + val db = AppDatabase.getAppDatabase(this) + val entries = db.entryDao().getAll() + Log.d(TAG, entries.get(10).toString()) + Unit + } + true + } + else -> super.onOptionsItemSelected(item) + } + } +} diff --git a/app/src/main/java/com/example/greenmangosongfinder/SongFragment.kt b/app/src/main/java/com/example/greenmangosongfinder/SongFragment.kt new file mode 100644 index 0000000..c44c4db --- /dev/null +++ b/app/src/main/java/com/example/greenmangosongfinder/SongFragment.kt @@ -0,0 +1,72 @@ +package com.example.greenmangosongfinder + +import android.content.Context +import android.os.Bundle +import androidx.fragment.app.Fragment +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import com.example.greenmangosongfinder.bin.database.AppDatabase +import com.example.greenmangosongfinder.bin.database.Entry + +/** + * A fragment representing a list of Items. + * Activities containing this fragment MUST implement the + * [SongFragment.OnListFragmentInteractionListener] interface. + */ +class SongFragment : Fragment() { + + private var listener: OnListFragmentInteractionListener? = null + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + } + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + val view = inflater.inflate(R.layout.activity_main, container, false) + + // Set the adapter + if (view is RecyclerView) { + with(view) { + layoutManager = LinearLayoutManager(context) + val db = AppDatabase.getAppDatabase(context) + adapter = EntryRecyclerViewAdapter(db.entryDao().getAll(), listener) + } + } + return view + } + + override fun onAttach(context: Context) { + super.onAttach(context) + if (context is OnListFragmentInteractionListener) { + listener = context + } else { + throw RuntimeException(context.toString() + " must implement OnListFragmentInteractionListener") + } + } + + override fun onDetach() { + super.onDetach() + listener = null + } + + /** + * This interface must be implemented by activities that contain this + * fragment to allow an interaction in this fragment to be communicated + * to the activity and potentially other fragments contained in that + * activity. + * + * + * See the Android Training lesson + * [Communicating with Other Fragments](http://developer.android.com/training/basics/fragments/communicating.html) + * for more information. + */ + interface OnListFragmentInteractionListener { + fun onItemSelected(item: Entry) + } +} diff --git a/app/src/main/java/com/example/greenmangosongfinder/bin/Download.kt b/app/src/main/java/com/example/greenmangosongfinder/bin/Download.kt new file mode 100644 index 0000000..bb23962 --- /dev/null +++ b/app/src/main/java/com/example/greenmangosongfinder/bin/Download.kt @@ -0,0 +1,188 @@ +package com.example.greenmangosongfinder.bin + +import android.content.Context +import android.text.BoringLayout +import android.util.Log +import androidx.room.Room +import com.android.volley.Request +import com.android.volley.Response +import com.android.volley.toolbox.StringRequest +import com.android.volley.toolbox.Volley +import com.android.volley.AuthFailureError +import com.example.greenmangosongfinder.bin.database.AppDatabase +import com.example.greenmangosongfinder.bin.database.Entry +import kotlinx.coroutines.* +import java.lang.Math.min +import com.android.volley.ParseError +import org.json.JSONException +import com.android.volley.toolbox.HttpHeaderParser +import org.json.JSONObject +import android.R.attr.data +import com.android.volley.NetworkResponse +import java.io.UnsupportedEncodingException +import java.nio.charset.Charset +import java.nio.charset.StandardCharsets + + +class Download(val context: Context) { + private val TAG = "Download" + + private val queue = Volley.newRequestQueue(context) + + fun get(url: String, response: Response.Listener, error: Response.ErrorListener) { + val stringRequest = object : StringRequest(Method.GET, url, response, error) { + override fun parseNetworkResponse(response: NetworkResponse): Response { + return try { + val utf8String = String(response.data, StandardCharsets.UTF_8) + Response.success(utf8String, HttpHeaderParser.parseCacheHeaders(response)) + } catch (e: UnsupportedEncodingException) { + // log error + Response.error(ParseError(e)) + } catch (e: JSONException) { + // log error + Response.error(ParseError(e)) + } + } + } + + // Add the request to the RequestQueue. + queue.add(stringRequest) + + } + + fun post(url: String, value: HashMap, response: Response.Listener, error: Response.ErrorListener) { + val stringRequest = object : StringRequest(Method.POST, url, response, error) { + @Throws(AuthFailureError::class) + override fun getParams(): Map { + return value + } + + override fun getBodyContentType(): String { + return "application/x-www-form-urlencoded; charset=UTF-8" + } + + override fun parseNetworkResponse(response: NetworkResponse): Response { + return try { + val utf8String = String(response.data, StandardCharsets.UTF_8) + Response.success(utf8String, HttpHeaderParser.parseCacheHeaders(response)) + } catch (e: UnsupportedEncodingException) { + // log error + Response.error(ParseError(e)) + } catch (e: JSONException) { + // log error + Response.error(ParseError(e)) + } + } + + } + + // Add the request to the RequestQueue. + queue.add(stringRequest) + + } + + fun refreshList2(cb: (Boolean) -> Unit) { + val regex = Regex("

(.*?)

(.*?)

(.*?)

(.*?)

") + val value = HashMap() + value.put("stichwort", "rzte") + value.put("formSprache", "Deutsch and Englisch") + value.put("Senden", "SONGS FINDEN") + post("https://www.greenmango24.de/songbook/", value, + Response.Listener { + GlobalScope.launch(Dispatchers.IO) { + long_d(TAG, it) + var j = 0 + var cnt = 0 + while (j < it.length) { + val next = min(it.length, j+1000) + val matches = regex.findAll(it.substring(j, next)) + long_d(TAG, matches.count().toString()) + matches.forEach { match -> + Log.d(TAG, match.groupValues.subList(1, match.groupValues.size).joinToString(separator = " ||| ") {str -> str.trim()}) + val entry = Entry( + match.groupValues[3].trim(), + match.groupValues[1].trim(), + match.groupValues[2].trim(), + match.groupValues[4].trim() + ) + cnt++ + Unit + } + val lastEntryEnd = it.substring(j, next).lastIndexOf("") + if (lastEntryEnd != -1) { + j = lastEntryEnd + j + 5 + } else { + j = next + } + } + } + }, + Response.ErrorListener { + Log.e(TAG, it.localizedMessage) + } + ) + } + + fun refreshList(cb: (Boolean) -> Unit) { + val db = AppDatabase.getAppDatabase(context) + val regex = Regex("

(.*?)

(.*?)

(.*?)

(.*?)

") + var count = 0 + val alphabet = "abcdefghijklmnopqrstuvwxyz" + val entries = ArrayList() + alphabet.toUpperCase().forEach { c: Char -> + val value = HashMap() + value.put(c.toString(), c.toString()) + post("https://www.greenmango24.de/songbook/", value, + Response.Listener { + GlobalScope.launch(Dispatchers.IO) { + var j = 0 + var cnt = 0 + while (j < it.length) { + val next = min(it.length, j+1000) + val matches = regex.findAll(it.substring(j, next)) + matches.forEach { match -> + //Log.d(TAG, match.groupValues.subList(1, match.groupValues.size).joinToString(separator = " ||| ") {str -> str.trim()}) + val entry = Entry( + match.groupValues[3].trim(), + match.groupValues[1].trim(), + match.groupValues[2].trim(), + match.groupValues[4].trim() + ) + entries.add(entry) + cnt++ + Unit + } + val lastEntryEnd = it.substring(j, next).lastIndexOf("") + if (lastEntryEnd != -1) { + j = lastEntryEnd + j + 5 + } else { + j = next + } + } + count++ + Log.d(TAG, "Count $count / ${alphabet.length} : Char $c - $cnt") + if (alphabet.length == count) { + Log.d(TAG, "Amount: ${entries.size}") + db.entryDao().insertAll(*entries.toTypedArray()) + cb(true) + } + } + }, + Response.ErrorListener { + Log.e(TAG, it.localizedMessage) + } + ) + } + } +} + +fun long_d(TAG: String, message: String) { + val maxLogSize = 2000 + for (i in 0..message.length / maxLogSize) { + + val start = i * maxLogSize + var end = (i + 1) * maxLogSize + end = if (end > message.length) message.length else end + Log.d(TAG, message.substring(start, end)) + } +} diff --git a/app/src/main/java/com/example/greenmangosongfinder/bin/database/AppDatabase.kt b/app/src/main/java/com/example/greenmangosongfinder/bin/database/AppDatabase.kt new file mode 100644 index 0000000..34af239 --- /dev/null +++ b/app/src/main/java/com/example/greenmangosongfinder/bin/database/AppDatabase.kt @@ -0,0 +1,37 @@ +package com.example.greenmangosongfinder.bin.database + +import android.content.Context +import androidx.room.Database +import androidx.room.RoomDatabase +import androidx.room.Room + + + +@Database(entities = arrayOf(Entry::class), version = 1) +abstract class AppDatabase : RoomDatabase() { + + companion object { + private val DATABASE_NAME = "app_database" + + private var INSTANCE: AppDatabase? = null + + fun getAppDatabase(context: Context): AppDatabase { + if (INSTANCE == null) { + INSTANCE = Room.databaseBuilder(context.getApplicationContext(), AppDatabase::class.java, DATABASE_NAME) + // allow queries on the main thread. + // Don't do this on a real app! See PersistenceBasicSample for an example. + .allowMainThreadQueries() + .build() + } + return INSTANCE!! + } + + fun destroyInstance() { + INSTANCE = null + } + } + + abstract fun entryDao(): EntryDao + + +} diff --git a/app/src/main/java/com/example/greenmangosongfinder/bin/database/Entry.kt b/app/src/main/java/com/example/greenmangosongfinder/bin/database/Entry.kt new file mode 100644 index 0000000..f0fbcb1 --- /dev/null +++ b/app/src/main/java/com/example/greenmangosongfinder/bin/database/Entry.kt @@ -0,0 +1,13 @@ +package com.example.greenmangosongfinder.bin.database + +import androidx.room.ColumnInfo +import androidx.room.Entity +import androidx.room.PrimaryKey + +@Entity +data class Entry( + @PrimaryKey val code: String, + @ColumnInfo(name = "artist") val artist: String, + @ColumnInfo(name = "title") val title: String, + @ColumnInfo(name = "language") val language: String +) diff --git a/app/src/main/java/com/example/greenmangosongfinder/bin/database/EntryDao.kt b/app/src/main/java/com/example/greenmangosongfinder/bin/database/EntryDao.kt new file mode 100644 index 0000000..95b3b61 --- /dev/null +++ b/app/src/main/java/com/example/greenmangosongfinder/bin/database/EntryDao.kt @@ -0,0 +1,25 @@ +package com.example.greenmangosongfinder.bin.database + +import androidx.room.* + +@Dao +interface EntryDao { + @Query("SELECT * FROM entry ORDER BY artist, title, code COLLATE latin1_german2_ci") + fun getAll(): List + + @Query("SELECT * FROM entry WHERE code IN (:entryCodes) ORDER BY artist, title, code COLLATE latin1_german2_ci") + fun loadAllByCodes(entryCodes: Array): List + + @Query("SELECT * FROM entry WHERE title LIKE :title ORDER BY artist, title, code COLLATE latin1_german2_ci") + fun findByTitle(title: String): Entry + + @Query("SELECT COUNT(code) FROM entry") + fun getCount(): Int + + + @Insert(onConflict = OnConflictStrategy.REPLACE) + fun insertAll(vararg entries: Entry) + + @Delete + fun delete(entry: Entry) +} diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..6348baa --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..a0ad202 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..2395912 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + \ 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 new file mode 100644 index 0000000..6290907 --- /dev/null +++ b/app/src/main/res/layout/content_main.xml @@ -0,0 +1,38 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_song.xml b/app/src/main/res/layout/fragment_song.xml new file mode 100644 index 0000000..9fad038 --- /dev/null +++ b/app/src/main/res/layout/fragment_song.xml @@ -0,0 +1,33 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_song_list.xml b/app/src/main/res/layout/fragment_song_list.xml new file mode 100644 index 0000000..1aab2ab --- /dev/null +++ b/app/src/main/res/layout/fragment_song_list.xml @@ -0,0 +1,14 @@ + + \ No newline at end of file diff --git a/app/src/main/res/menu/menu_main.xml b/app/src/main/res/menu/menu_main.xml new file mode 100644 index 0000000..6bbb363 --- /dev/null +++ b/app/src/main/res/menu/menu_main.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..bbd3e02 --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..bbd3e02 --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..898f3ed Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000..dffca36 Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..64ba76f Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000..dae5e08 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..e5ed465 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000..14ed0af Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..b0907ca Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..d8ae031 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..2c18de9 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..beed3cd Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..69b2233 --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,6 @@ + + + #008577 + #00574B + #D81B60 + diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml new file mode 100644 index 0000000..ef77d84 --- /dev/null +++ b/app/src/main/res/values/dimens.xml @@ -0,0 +1,4 @@ + + 16dp + 16dp + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..c5de9b6 --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,4 @@ + + Green Mango Songfinder + Settings + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..16dbab3 --- /dev/null +++ b/app/src/main/res/values/styles.xml @@ -0,0 +1,17 @@ + + + + + +