Add ability to open a ROM directly and Make URI Persistent

Before ROMs needed to be opened by setting the path, now they can be directly opened using the file picker. In addition, Document Tree URIs are now set to be persistent rather than being revoked after reboot.
This commit is contained in:
◱ PixelyIon 2019-12-10 15:43:19 +05:30 committed by ◱ PixelyIon
parent c5dce22a8c
commit 4ab9af04ff
5 changed files with 74 additions and 22 deletions

View File

@ -4,25 +4,26 @@ import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.provider.OpenableColumns
import android.util.Log import android.util.Log
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import android.widget.AdapterView import android.widget.AdapterView
import android.widget.AdapterView.OnItemClickListener import android.widget.AdapterView.OnItemClickListener
import android.widget.ListView
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.SearchView
import androidx.documentfile.provider.DocumentFile import androidx.documentfile.provider.DocumentFile
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import emu.skyline.adapter.GameAdapter import emu.skyline.adapter.GameAdapter
import emu.skyline.adapter.GameItem import emu.skyline.adapter.GameItem
import emu.skyline.loader.BaseLoader import emu.skyline.loader.BaseLoader
import emu.skyline.loader.NroLoader import emu.skyline.loader.NroLoader
import emu.skyline.loader.TitleEntry import emu.skyline.loader.TitleEntry
import emu.skyline.loader.TitleFormat
import emu.skyline.utility.RandomAccessDocument import emu.skyline.utility.RandomAccessDocument
import kotlinx.android.synthetic.main.main_activity.*
import java.io.File import java.io.File
import java.io.IOException import java.io.IOException
import java.util.* import java.util.*
@ -88,12 +89,11 @@ class MainActivity : AppCompatActivity(), View.OnClickListener {
setContentView(R.layout.main_activity) setContentView(R.layout.main_activity)
PreferenceManager.setDefaultValues(this, R.xml.preferences, false) PreferenceManager.setDefaultValues(this, R.xml.preferences, false)
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this) sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
setSupportActionBar(findViewById(R.id.toolbar)) setSupportActionBar(toolbar)
val logFab = findViewById<FloatingActionButton>(R.id.log_fab) open_fab.setOnClickListener(this)
logFab.setOnClickListener(this) log_fab.setOnClickListener(this)
val gameList = findViewById<ListView>(R.id.game_list) game_list.adapter = adapter
gameList.adapter = adapter game_list.onItemClickListener = OnItemClickListener { parent: AdapterView<*>, _: View?, position: Int, _: Long ->
gameList.onItemClickListener = OnItemClickListener { parent: AdapterView<*>, _: View?, position: Int, _: Long ->
val item = parent.getItemAtPosition(position) val item = parent.getItemAtPosition(position)
if (item is GameItem) { if (item is GameItem) {
val intent = Intent(this, GameActivity::class.java) val intent = Intent(this, GameActivity::class.java)
@ -104,7 +104,8 @@ class MainActivity : AppCompatActivity(), View.OnClickListener {
} }
if (sharedPreferences.getString("search_location", "") == "") { if (sharedPreferences.getString("search_location", "") == "") {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
this.startActivityForResult(intent, 1) intent.flags = Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION or Intent.FLAG_GRANT_PREFIX_URI_PERMISSION or Intent.FLAG_GRANT_READ_URI_PERMISSION
startActivityForResult(intent, 1)
} else } else
refreshFiles(!sharedPreferences.getBoolean("refresh_required", false)) refreshFiles(!sharedPreferences.getBoolean("refresh_required", false))
} }
@ -129,7 +130,15 @@ class MainActivity : AppCompatActivity(), View.OnClickListener {
} }
override fun onClick(view: View) { override fun onClick(view: View) {
if (view.id == R.id.log_fab) startActivity(Intent(this, LogActivity::class.java)) when (view.id) {
R.id.log_fab -> startActivity(Intent(this, LogActivity::class.java))
R.id.open_fab -> {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
intent.addCategory(Intent.CATEGORY_OPENABLE)
intent.type = "*/*"
startActivityForResult(intent, 2)
}
}
} }
override fun onOptionsItemSelected(item: MenuItem): Boolean { override fun onOptionsItemSelected(item: MenuItem): Boolean {
@ -156,10 +165,32 @@ class MainActivity : AppCompatActivity(), View.OnClickListener {
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data) super.onActivityResult(requestCode, resultCode, data)
if (resultCode == RESULT_OK) { if (resultCode == RESULT_OK) {
if (requestCode == 1) { when (requestCode) {
sharedPreferences.edit().putString("search_location", data!!.data.toString()).apply() 1 -> {
val uri = data!!.data!!
contentResolver.takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION)
sharedPreferences.edit().putString("search_location", uri.toString()).apply()
refreshFiles(!sharedPreferences.getBoolean("refresh_required", false)) refreshFiles(!sharedPreferences.getBoolean("refresh_required", false))
} }
2 -> {
try {
val intent = Intent(this, GameActivity::class.java)
val uri = data!!.data!!
intent.putExtra("romUri", uri)
var uriStr = ""
contentResolver.query(uri, null, null, null, null)?.use { cursor ->
val nameIndex: Int = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
cursor.moveToFirst()
uriStr = cursor.getString(nameIndex)
}
val type = TitleFormat.valueOf(uriStr.substring(uriStr.lastIndexOf(".") + 1).toUpperCase(Locale.ROOT))
intent.putExtra("romType", type)
startActivity(intent)
} catch (e: Exception) {
notifyUser(e.message!!)
}
}
}
} }
} }
} }

View File

@ -17,8 +17,10 @@ class FolderActivity : AppCompatActivity() {
super.onActivityResult(requestCode, resultCode, data) super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK) { if (resultCode == Activity.RESULT_OK) {
if (requestCode == 1) { if (requestCode == 1) {
val uri = data!!.data!!
contentResolver.takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION)
PreferenceManager.getDefaultSharedPreferences(this).edit() PreferenceManager.getDefaultSharedPreferences(this).edit()
.putString("search_location", data!!.data.toString()) .putString("search_location", uri.toString())
.putBoolean("refresh_required", true) .putBoolean("refresh_required", true)
.apply() .apply()
finish() finish()

View File

@ -1,7 +1,6 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp" android:width="24dp"
android:height="24dp" android:height="24dp"
android:alpha="0.85"
android:viewportWidth="24.0" android:viewportWidth="24.0"
android:viewportHeight="24.0"> android:viewportHeight="24.0">
<path <path

View File

@ -0,0 +1,5 @@
<vector android:height="24dp"
android:tint="#FFFFFF" android:viewportHeight="24.0"
android:viewportWidth="24.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M19,4L5,4c-1.11,0 -2,0.9 -2,2v12c0,1.1 0.89,2 2,2h4v-2L5,18L5,8h14v10h-4v2h4c1.1,0 2,-0.9 2,-2L21,6c0,-1.1 -0.89,-2 -2,-2zM12,10l-4,4h3v6h2v-6h3l-4,-4z"/>
</vector>

View File

@ -27,16 +27,31 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/toolbar" /> app:layout_constraintTop_toBottomOf="@+id/toolbar" />
<com.google.android.material.floatingactionbutton.FloatingActionButton <LinearLayout
android:id="@+id/log_fab"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="16dp" android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp" android:layout_marginBottom="16dp"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/open_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:clickable="true"
android:focusable="true"
app:srcCompat="@drawable/ic_open" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/log_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true" android:clickable="true"
android:focusable="true" android:focusable="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:srcCompat="@drawable/ic_log" /> app:srcCompat="@drawable/ic_log" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>