Skip to content

Commit

Permalink
Switch to viewbinding and di with hilt
Browse files Browse the repository at this point in the history
  • Loading branch information
Grarak authored and PixelyIon committed Jun 17, 2021
1 parent ff1b9cb commit f5d5caf
Show file tree
Hide file tree
Showing 41 changed files with 714 additions and 578 deletions.
4 changes: 4 additions & 0 deletions .idea/codeStyles/Project.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 13 additions & 11 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-kapt'
id 'dagger.hilt.android.plugin'
}

android {
compileSdkVersion 30
Expand Down Expand Up @@ -51,14 +54,7 @@ android {
}
}
buildFeatures {
prefab true
viewBinding false
}

/* Android Extensions */
androidExtensions {
/* TODO: Remove this after migrating to View Bindings */
experimental = true
viewBinding true
}

/* Linting */
Expand All @@ -79,6 +75,10 @@ android {
aaptOptions {
ignoreAssetsPattern "*.md"
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}

dependencies {
Expand All @@ -99,6 +99,8 @@ dependencies {
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
implementation 'androidx.fragment:fragment-ktx:1.2.5'
implementation "com.google.dagger:hilt-android:$hilt_version"
kapt "com.google.dagger:hilt-android-compiler:$hilt_version"

/* Kotlin */
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
Expand Down
28 changes: 12 additions & 16 deletions app/src/main/java/emu/skyline/AppDialog.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ import androidx.core.graphics.drawable.toBitmap
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import emu.skyline.data.AppItem
import emu.skyline.databinding.AppDialogBinding
import emu.skyline.loader.LoaderResult
import kotlinx.android.synthetic.main.app_dialog.*

/**
* This dialog is used to show extra game metadata and provide extra options such as pinning the game to the home screen
Expand All @@ -41,19 +41,15 @@ class AppDialog : BottomSheetDialogFragment() {
}
}

private lateinit var item : AppItem
private lateinit var binding : AppDialogBinding

private val item by lazy { requireArguments().getSerializable("item") as AppItem }

/**
* This inflates the layout of the dialog after initial view creation
*/
override fun onCreateView(inflater : LayoutInflater, container : ViewGroup?, savedInstanceState : Bundle?) : View? {
return requireActivity().layoutInflater.inflate(R.layout.app_dialog, container)
}

override fun onCreate(savedInstanceState : Bundle?) {
super.onCreate(savedInstanceState)

item = requireArguments().getSerializable("item") as AppItem
return AppDialogBinding.inflate(inflater).also { binding = it }.root
}

/**
Expand Down Expand Up @@ -82,19 +78,19 @@ class AppDialog : BottomSheetDialogFragment() {

val missingIcon = ContextCompat.getDrawable(requireActivity(), R.drawable.default_icon)!!.toBitmap(256, 256)

game_icon.setImageBitmap(item.icon ?: missingIcon)
game_title.text = item.title
game_subtitle.text = item.subTitle ?: item.loaderResultString(requireContext())
binding.gameIcon.setImageBitmap(item.icon ?: missingIcon)
binding.gameTitle.text = item.title
binding.gameSubtitle.text = item.subTitle ?: item.loaderResultString(requireContext())

game_play.isEnabled = item.loaderResult == LoaderResult.Success
game_play.setOnClickListener {
binding.gamePlay.isEnabled = item.loaderResult == LoaderResult.Success
binding.gamePlay.setOnClickListener {
startActivity(Intent(activity, EmulationActivity::class.java).apply { data = item.uri })
}

val shortcutManager = requireActivity().getSystemService(ShortcutManager::class.java)
game_pin.isEnabled = shortcutManager.isRequestPinShortcutSupported
binding.gamePin.isEnabled = shortcutManager.isRequestPinShortcutSupported

game_pin.setOnClickListener {
binding.gamePin.setOnClickListener {
val info = ShortcutInfo.Builder(context, item.title)
info.setShortLabel(item.title)
info.setActivity(ComponentName(requireContext(), EmulationActivity::class.java))
Expand Down
66 changes: 39 additions & 27 deletions app/src/main/java/emu/skyline/EmulationActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@ import android.view.*
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.isGone
import androidx.core.view.isInvisible
import dagger.hilt.android.AndroidEntryPoint
import emu.skyline.databinding.EmuActivityBinding
import emu.skyline.input.*
import emu.skyline.loader.getRomFormat
import emu.skyline.utils.Settings
import kotlinx.android.synthetic.main.emu_activity.*
import java.io.File
import javax.inject.Inject
import kotlin.math.abs

@AndroidEntryPoint
class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTouchListener {
companion object {
private val Tag = EmulationActivity::class.java.simpleName
Expand All @@ -33,8 +36,10 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
System.loadLibrary("skyline") // libskyline.so
}

private val binding by lazy { EmuActivityBinding.inflate(layoutInflater) }

/**
* A map of [Vibrator]s that correspond to [InputManager.controllers]
* A map of [Vibrator]s that correspond to [inputManager.controllers]
*/
private var vibrators = HashMap<Int, Vibrator>()

Expand All @@ -51,6 +56,9 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo

private val settings by lazy { Settings(this) }

@Inject
lateinit var inputManager : InputManager

/**
* This is the entry point into the emulation code for libskyline
*
Expand Down Expand Up @@ -131,7 +139,7 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
*/
@Suppress("unused")
private fun initializeControllers() {
for (controller in InputManager.controllers.values) {
for (controller in inputManager.controllers.values) {
if (controller.type != ControllerType.None) {
val type = when (controller.type) {
ControllerType.None -> throw IllegalArgumentException()
Expand Down Expand Up @@ -177,11 +185,11 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
/**
* This makes the window fullscreen, sets up the performance statistics and finally calls [executeApplication] for executing the application
*/
@SuppressLint("SetTextI18n")
@SuppressLint("SetTextI18n", "ClickableViewAccessibility")
override fun onCreate(savedInstanceState : Bundle?) {
super.onCreate(savedInstanceState)

setContentView(R.layout.emu_activity)
setContentView(binding.root)

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
window.insetsController?.hide(WindowInsets.Type.navigationBars() or WindowInsets.Type.systemBars() or WindowInsets.Type.systemGestures() or WindowInsets.Type.statusBars())
Expand All @@ -196,32 +204,36 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
or View.SYSTEM_UI_FLAG_FULLSCREEN)
}

game_view.holder.addCallback(this)
binding.gameView.holder.addCallback(this)

if (settings.perfStats) {
perf_stats.postDelayed(object : Runnable {
override fun run() {
updatePerformanceStatistics()
perf_stats.text = "$fps FPS\n${frametime}ms"
perf_stats.postDelayed(this, 250)
}
}, 250)
binding.perfStats.apply {
postDelayed(object : Runnable {
override fun run() {
updatePerformanceStatistics()
text = "$fps FPS\n${frametime}ms"
postDelayed(this, 250)
}
}, 250)
}
}

@Suppress("DEPRECATION") val display = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) display!! else windowManager.defaultDisplay
display?.supportedModes?.maxByOrNull { it.refreshRate + (it.physicalHeight * it.physicalWidth) }?.let { window.attributes.preferredDisplayModeId = it.modeId }

game_view.setOnTouchListener(this)
binding.gameView.setOnTouchListener(this)

// Hide on screen controls when first controller is not set
on_screen_controller_view.isGone = InputManager.controllers[0]!!.type == ControllerType.None || !settings.onScreenControl
on_screen_controller_view.setOnButtonStateChangedListener(::onButtonStateChanged)
on_screen_controller_view.setOnStickStateChangedListener(::onStickStateChanged)
on_screen_controller_view.recenterSticks = settings.onScreenControlRecenterSticks

on_screen_controller_toggle.isGone = on_screen_controller_view.isGone
on_screen_controller_toggle.setOnClickListener {
on_screen_controller_view.isInvisible = !on_screen_controller_view.isInvisible
binding.onScreenControllerView.apply {
isGone = inputManager.controllers[0]!!.type == ControllerType.None || !settings.onScreenControl
setOnButtonStateChangedListener(::onButtonStateChanged)
setOnStickStateChangedListener(::onStickStateChanged)
recenterSticks = settings.onScreenControlRecenterSticks
}

binding.onScreenControllerToggle.apply {
isGone = binding.onScreenControllerView.isGone
setOnClickListener { binding.onScreenControllerView.isInvisible = !binding.onScreenControllerView.isInvisible }
}

executeApplication(intent.data!!)
Expand Down Expand Up @@ -291,7 +303,7 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
else -> return super.dispatchKeyEvent(event)
}

return when (val guestEvent = InputManager.eventMap[KeyHostEvent(event.device.descriptor, event.keyCode)]) {
return when (val guestEvent = inputManager.eventMap[KeyHostEvent(event.device.descriptor, event.keyCode)]) {
is ButtonGuestEvent -> {
if (guestEvent.button != ButtonId.Menu)
setButtonState(guestEvent.id, guestEvent.button.value(), action.state)
Expand Down Expand Up @@ -333,9 +345,9 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
var polarity = value >= 0

val guestEvent = MotionHostEvent(event.device.descriptor, axis, polarity).let { hostEvent ->
InputManager.eventMap[hostEvent] ?: if (value == 0f) {
inputManager.eventMap[hostEvent] ?: if (value == 0f) {
polarity = false
InputManager.eventMap[hostEvent.copy(polarity = false)]
inputManager.eventMap[hostEvent.copy(polarity = false)]
} else {
null
}
Expand Down Expand Up @@ -413,15 +425,15 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
val vibrator = if (vibrators[index] != null) {
vibrators[index]!!
} else {
InputManager.controllers[index]!!.rumbleDeviceDescriptor?.let {
inputManager.controllers[index]!!.rumbleDeviceDescriptor?.let {
if (it == "builtin") {
val vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
vibrators[index] = vibrator
vibrator
} else {
for (id in InputDevice.getDeviceIds()) {
val device = InputDevice.getDevice(id)
if (device.descriptor == InputManager.controllers[index]!!.rumbleDeviceDescriptor) {
if (device.descriptor == inputManager.controllers[index]!!.rumbleDeviceDescriptor) {
vibrators[index] = device.vibrator
device.vibrator
}
Expand Down
20 changes: 7 additions & 13 deletions app/src/main/java/emu/skyline/LogActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,8 @@ import com.google.android.material.snackbar.Snackbar
import emu.skyline.adapter.GenericAdapter
import emu.skyline.adapter.HeaderViewItem
import emu.skyline.adapter.LogViewItem
import emu.skyline.databinding.LogActivityBinding
import emu.skyline.utils.Settings
import kotlinx.android.synthetic.main.log_activity.*
import kotlinx.android.synthetic.main.titlebar.*
import org.json.JSONObject
import java.io.File
import java.io.FileNotFoundException
Expand All @@ -31,25 +30,21 @@ import java.net.URL
import javax.net.ssl.HttpsURLConnection

class LogActivity : AppCompatActivity() {
private val binding by lazy { LogActivityBinding.inflate(layoutInflater) }

/**
* The log file is used to read log entries from or to clear all entries
*/
private lateinit var logFile : File

/**
* The adapter used for adding elements from the log to [log_list]
*/
private val adapter = GenericAdapter()

/**
* This initializes [toolbar] and fills [log_list] with data from the logs
*/
override fun onCreate(savedInstanceState : Bundle?) {
super.onCreate(savedInstanceState)

setContentView(R.layout.log_activity)
setContentView(binding.root)

setSupportActionBar(toolbar)
setSupportActionBar(binding.titlebar.toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)

val settings = Settings(this)
Expand All @@ -58,10 +53,9 @@ class LogActivity : AppCompatActivity() {
val logLevel = settings.logLevel.toInt()
val logLevels = resources.getStringArray(R.array.log_level)

log_list.adapter = adapter
binding.logList.adapter = adapter

if (!compact)
log_list.addItemDecoration(DividerItemDecoration(this, RecyclerView.VERTICAL))
if (!compact) binding.logList.addItemDecoration(DividerItemDecoration(this, RecyclerView.VERTICAL))

try {
logFile = File(applicationContext.filesDir.canonicalPath + "/skyline.log")
Expand Down
Loading

0 comments on commit f5d5caf

Please sign in to comment.