diff --git a/app/build.gradle b/app/build.gradle index 5e3445fc..a34d498e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -4,7 +4,7 @@ apply plugin: 'kotlin-android-extensions' android { compileSdkVersion 29 - buildToolsVersion '29.0.2' + buildToolsVersion '29.0.3' defaultConfig { applicationId "skyline.emu" minSdkVersion 26 @@ -47,6 +47,7 @@ android { sourceCompatibility = 1.8 targetCompatibility = 1.8 } + ndkVersion '21.0.6113669' } dependencies { @@ -54,9 +55,9 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'androidx.preference:preference:1.1.0' - implementation 'com.google.android.material:material:1.2.0-alpha02' + implementation 'com.google.android.material:material:1.2.0-alpha05' implementation 'me.xdrop:fuzzywuzzy:1.2.0' - implementation "androidx.core:core-ktx:1.1.0" + implementation "androidx.core:core-ktx:1.2.0" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation 'androidx.documentfile:documentfile:1.0.1' } diff --git a/app/src/main/java/emu/skyline/LogActivity.kt b/app/src/main/java/emu/skyline/LogActivity.kt index d8ccacf1..e0eedaa8 100644 --- a/app/src/main/java/emu/skyline/LogActivity.kt +++ b/app/src/main/java/emu/skyline/LogActivity.kt @@ -26,32 +26,23 @@ class LogActivity : AppCompatActivity() { super.onCreate(savedInstanceState) setContentView(R.layout.log_activity) setSupportActionBar(findViewById(R.id.toolbar)) - val actionBar = supportActionBar - actionBar?.setDisplayHomeAsUpEnabled(true) + supportActionBar?.setDisplayHomeAsUpEnabled(true) val prefs = PreferenceManager.getDefaultSharedPreferences(this) val logList = findViewById(R.id.log_list) adapter = LogAdapter(this, prefs.getBoolean("log_compact", false), prefs.getString("log_level", "3")!!.toInt(), resources.getStringArray(R.array.log_level)) logList.adapter = adapter try { - logFile = File(applicationInfo.dataDir + "/skyline.log") - val inputStream: InputStream = FileInputStream(logFile) - val reader = BufferedReader(InputStreamReader(inputStream)) - try { - var done = false - while (!done) { - val line = reader.readLine() - if (!(line == null).also { done = it }) { - adapter.add(line) - } - } - } catch (e: IOException) { - Log.w("Logger", "IO Error during access of log file: " + e.message) - Toast.makeText(applicationContext, getString(R.string.io_error) + ": " + e.message, Toast.LENGTH_LONG).show() + logFile = File("${applicationInfo.dataDir}/skyline.log") + logFile.forEachLine { + adapter.add(it) } } catch (e: FileNotFoundException) { Log.w("Logger", "IO Error during access of log file: " + e.message) Toast.makeText(applicationContext, getString(R.string.file_missing), Toast.LENGTH_LONG).show() finish() + } catch (e: IOException) { + Log.w("Logger", "IO Error during access of log file: " + e.message) + Toast.makeText(applicationContext, getString(R.string.io_error) + ": " + e.message, Toast.LENGTH_LONG).show() } } @@ -78,8 +69,7 @@ class LogActivity : AppCompatActivity() { return when (item.itemId) { R.id.action_clear -> { try { - val fileWriter = FileWriter(logFile, false) - fileWriter.close() + logFile.writeText("") } catch (e: IOException) { Log.w("Logger", "IO Error while clearing the log file: " + e.message) Toast.makeText(applicationContext, getString(R.string.io_error) + ": " + e.message, Toast.LENGTH_LONG).show() @@ -89,56 +79,50 @@ class LogActivity : AppCompatActivity() { true } R.id.action_share_log -> { - val shareThread = Thread(Runnable { - var urlConnection: HttpsURLConnection? = null - try { - val url = URL("https://hastebin.com/documents") - urlConnection = url.openConnection() as HttpsURLConnection - urlConnection.requestMethod = "POST" - urlConnection.setRequestProperty("Host", "hastebin.com") - urlConnection.setRequestProperty("Content-Type", "application/json; charset=utf-8") - urlConnection.setRequestProperty("Referer", "https://hastebin.com/") - urlConnection.setRequestProperty("Connection", "keep-alive") - val outputStream: OutputStream = BufferedOutputStream(urlConnection.outputStream) - val bufferedWriter = BufferedWriter(OutputStreamWriter(outputStream, StandardCharsets.UTF_8)) - val fileReader = FileReader(logFile) - var chr: Int - while (fileReader.read().also { chr = it } != -1) { - bufferedWriter.write(chr) - } - bufferedWriter.flush() - bufferedWriter.close() - outputStream.close() - if (urlConnection.responseCode != 200) { - Log.e("LogUpload", "HTTPS Status Code: " + urlConnection.responseCode) - throw Exception() - } - val inputStream: InputStream = BufferedInputStream(urlConnection.inputStream) - val bufferedReader = BufferedReader(InputStreamReader(inputStream, StandardCharsets.UTF_8)) - val key = JSONObject(bufferedReader.lines().collect(Collectors.joining())).getString("key") - bufferedReader.close() - inputStream.close() - val result = "https://hastebin.com/$key" - val sharingIntent = Intent(Intent.ACTION_SEND).setType("text/plain").putExtra(Intent.EXTRA_TEXT, result) - startActivity(Intent.createChooser(sharingIntent, "Share log url with:")) - } catch (e: Exception) { - runOnUiThread { Toast.makeText(applicationContext, getString(R.string.share_error), Toast.LENGTH_LONG).show() } - e.printStackTrace() - } finally { - assert(urlConnection != null) - urlConnection!!.disconnect() - } - }) - shareThread.start() - try { - shareThread.join(1000) - } catch (e: Exception) { - Toast.makeText(applicationContext, getString(R.string.share_error), Toast.LENGTH_LONG).show() - e.printStackTrace() - } - super.onOptionsItemSelected(item) + uploadAndShareLog() + true } else -> super.onOptionsItemSelected(item) } } + + private fun uploadAndShareLog() { + val shareThread = Thread(Runnable { + var urlConnection: HttpsURLConnection? = null + try { + val url = URL("https://hastebin.com/documents") + urlConnection = url.openConnection() as HttpsURLConnection + urlConnection.requestMethod = "POST" + urlConnection.setRequestProperty("Host", "hastebin.com") + urlConnection.setRequestProperty("Content-Type", "application/json; charset=utf-8") + urlConnection.setRequestProperty("Referer", "https://hastebin.com/") + val bufferedWriter = urlConnection.outputStream.bufferedWriter() + bufferedWriter.write(logFile.readText()) + bufferedWriter.flush() + bufferedWriter.close() + if (urlConnection.responseCode != 200) { + Log.e("LogUpload", "HTTPS Status Code: " + urlConnection.responseCode) + throw Exception() + } + val bufferedReader = urlConnection.inputStream.bufferedReader() + val key = JSONObject(bufferedReader.readText()).getString("key") + bufferedReader.close() + val result = "https://hastebin.com/$key" + val sharingIntent = Intent(Intent.ACTION_SEND).setType("text/plain").putExtra(Intent.EXTRA_TEXT, result) + startActivity(Intent.createChooser(sharingIntent, "Share log url with:")) + } catch (e: Exception) { + runOnUiThread { Toast.makeText(applicationContext, getString(R.string.share_error), Toast.LENGTH_LONG).show() } + e.printStackTrace() + } finally { + urlConnection!!.disconnect() + } + }) + shareThread.start() + try { + shareThread.join(1000) + } catch (e: Exception) { + Toast.makeText(applicationContext, getString(R.string.share_error), Toast.LENGTH_LONG).show() + e.printStackTrace() + } + } } diff --git a/app/src/main/java/emu/skyline/MainActivity.kt b/app/src/main/java/emu/skyline/MainActivity.kt index bb198e0b..7f1f338b 100644 --- a/app/src/main/java/emu/skyline/MainActivity.kt +++ b/app/src/main/java/emu/skyline/MainActivity.kt @@ -27,53 +27,49 @@ import java.io.File import java.io.IOException import kotlin.concurrent.thread - class MainActivity : AppCompatActivity(), View.OnClickListener { private lateinit var sharedPreferences: SharedPreferences private var adapter = GameAdapter(this) - fun notifyUser(text: String) { + private fun notifyUser(text: String) { Snackbar.make(findViewById(android.R.id.content), text, Snackbar.LENGTH_SHORT).show() } private fun findFile(ext: String, loader: BaseLoader, directory: DocumentFile, entries: Int = 0): Int { - var mEntries = entries - for (file in directory.listFiles()) { - if (file.isDirectory) { - mEntries = findFile(ext, loader, file, mEntries) - } else { - try { - if (file.name != null) { - if (ext.equals(file.name?.substring((file.name!!.lastIndexOf(".")) + 1), ignoreCase = true)) { - val document = RandomAccessDocument(this, file) - if (loader.verifyFile(document)) { - val entry = loader.getTitleEntry(document, file.uri) - val header = (mEntries == 0) - runOnUiThread { - if(header) - adapter.addHeader(getString(R.string.nro)) - adapter.addItem(GameItem(entry)) - } - mEntries++ + var entryCount = entries + + directory.listFiles() + .forEach { file -> + if (file.isDirectory) { + entryCount = findFile(ext, loader, file, entries) + } else { + if (ext.equals(file.name?.substringAfterLast("."), ignoreCase = true)) { + val document = RandomAccessDocument(this, file) + if (loader.verifyFile(document)) { + val entry = loader.getTitleEntry(document, file.uri) + val header = (entryCount == 0) + runOnUiThread { + if (header) + adapter.addHeader(getString(R.string.nro)) + adapter.addItem(GameItem(entry)) } - document.close() + entryCount++ } + document.close() } - } catch (e: StringIndexOutOfBoundsException) { - Log.w("findFile", e.message!!) } } - } - return mEntries + + return entryCount } private fun refreshFiles(tryLoad: Boolean) { if (tryLoad) { try { - adapter.load(File(applicationInfo.dataDir + "/roms.bin")) + adapter.load(File("${applicationInfo.dataDir}/roms.bin")) return } catch (e: Exception) { - Log.w("refreshFiles", "Ran into exception while loading: " + e.message) + Log.w("refreshFiles", "Ran into exception while loading: ${e.message}") } } thread(start = true) { @@ -86,9 +82,9 @@ class MainActivity : AppCompatActivity(), View.OnClickListener { if (entries == 0) adapter.addHeader(getString(R.string.no_rom)) try { - adapter.save(File(applicationInfo.dataDir + "/roms.bin")) + adapter.save(File("${applicationInfo.dataDir}/roms.bin")) } catch (e: IOException) { - Log.w("refreshFiles", "Ran into exception while saving: " + e.message) + Log.w("refreshFiles", "Ran into exception while saving: ${e.message}") } } sharedPreferences.edit().putBoolean("refresh_required", false).apply() diff --git a/app/src/main/java/emu/skyline/utility/GameDialog.kt b/app/src/main/java/emu/skyline/utility/GameDialog.kt index d4b6d966..7c726ce3 100644 --- a/app/src/main/java/emu/skyline/utility/GameDialog.kt +++ b/app/src/main/java/emu/skyline/utility/GameDialog.kt @@ -35,24 +35,20 @@ class GameDialog() : DialogFragment() { val shortcutManager = activity?.getSystemService(ShortcutManager::class.java)!! game_pin.isEnabled = shortcutManager.isRequestPinShortcutSupported game_pin.setOnClickListener { - run { - val info = ShortcutInfo.Builder(context, item?.title) - info.setShortLabel(item?.meta?.name!!) - info.setActivity(ComponentName(context!!, GameActivity::class.java)) - info.setIcon(Icon.createWithBitmap(item?.icon)) - val intent = Intent(context, GameActivity::class.java) - intent.data = item?.uri - intent.action = Intent.ACTION_VIEW - info.setIntent(intent) - shortcutManager.requestPinShortcut(info.build(), null) - } + val info = ShortcutInfo.Builder(context, item?.title) + info.setShortLabel(item?.meta?.name!!) + info.setActivity(ComponentName(context!!, GameActivity::class.java)) + info.setIcon(Icon.createWithBitmap(item?.icon)) + val intent = Intent(context, GameActivity::class.java) + intent.data = item?.uri + intent.action = Intent.ACTION_VIEW + info.setIntent(intent) + shortcutManager.requestPinShortcut(info.build(), null) } game_play.setOnClickListener { - run { - val intent = Intent(activity, GameActivity::class.java) - intent.data = item?.uri - startActivity(intent) - } + val intent = Intent(activity, GameActivity::class.java) + intent.data = item?.uri + startActivity(intent) } } else activity?.supportFragmentManager?.beginTransaction()?.remove(this)?.commit() diff --git a/build.gradle b/build.gradle index e546a246..9d504c73 100644 --- a/build.gradle +++ b/build.gradle @@ -1,14 +1,14 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.3.60' + ext.kotlin_version = '1.3.61' repositories { google() jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.5.3' + classpath 'com.android.tools.build:gradle:3.6.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong @@ -16,6 +16,10 @@ buildscript { } } +plugins { + id "com.github.ben-manes.versions" version "0.28.0" +} + allprojects { repositories { google() diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index efb82282..b754edfe 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.2.1-all.zip