commit c2a568f5d3246445eb202713253b26819c5c8e49 Author: Davide Depau Date: Sun Aug 12 16:33:11 2018 +0200 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..daaeaef --- /dev/null +++ b/.gitignore @@ -0,0 +1,123 @@ + +*.iml +.gradle +/local.properties + +.DS_Store +/build +/captures +.externalNativeBuild +### Java template +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +.idea + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/modules.xml +# .idea/*.iml +# .idea/modules + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests +### Android template +# Built application files +*.apk +*.ap_ + +# Files for the ART/Dalvik VM +*.dex + +# Java class files +# Generated files +bin/ +gen/ +# Gradle files +build/ + +# Local configuration file (sdk path, etc) +# Proguard folder generated by Eclipse +proguard/ + +# Log Files +# Android Studio Navigation editor temp files +.navigation/ + +# Android Studio captures folder +captures/ + + +# Keystore files +# Uncomment the following line if you do not want to check your keystore files in. +#*.jks + +# External native build folder generated in Android Studio 2.2 and later +# Google Services (e.g. APIs or Firebase) +google-services.json + +# Freeline +freeline.py +freeline/ +freeline_project_description.json + +# fastlane +fastlane/report.xml +fastlane/Preview.html +fastlane/screenshots +fastlane/test_output +fastlane/readme.md + 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/build.gradle b/app/build.gradle new file mode 100644 index 0000000..8af2f7e --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,37 @@ +apply plugin: 'com.android.application' + +apply plugin: 'kotlin-android' + +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 28 + defaultConfig { + applicationId "eu.depau.ddroid" + minSdkVersion 19 + targetSdkVersion 28 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + android.defaultConfig.vectorDrawables.useSupportLibrary = true + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation 'com.android.support:appcompat-v7:28.0.0-rc01' + implementation 'com.android.support.constraint:constraint-layout:1.1.2' + implementation 'com.android.support:design:28.0.0-rc01' + implementation 'com.android.support:recyclerview-v7:28.0.0-rc01' + implementation 'com.github.mjdev:libaums:0.5.5' + testImplementation 'junit:junit:4.12' + androidTestImplementation 'com.android.support.test:runner:1.0.2' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' +} 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/eu/depau/ddroid/ExampleInstrumentedTest.kt b/app/src/androidTest/java/eu/depau/ddroid/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..696e183 --- /dev/null +++ b/app/src/androidTest/java/eu/depau/ddroid/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package eu.depau.ddroid + +import android.support.test.InstrumentationRegistry +import android.support.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("eu.depau.ddroid", appContext.packageName) + } +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..86406c7 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/eu/depau/ddroid/StateKeeper.kt b/app/src/main/java/eu/depau/ddroid/StateKeeper.kt new file mode 100644 index 0000000..bbf3656 --- /dev/null +++ b/app/src/main/java/eu/depau/ddroid/StateKeeper.kt @@ -0,0 +1,16 @@ +package eu.depau.ddroid + +import android.net.Uri +import eu.depau.ddroid.abc.WizardFragment +import eu.depau.ddroid.values.FlashMethod +import eu.depau.ddroid.values.ImageLocation +import eu.depau.ddroid.values.WizardStep + +object StateKeeper { + var wizardStep: WizardStep = WizardStep.SELECT_FLASH_METHOD + var currentFragment: WizardFragment? = null + var flashMethod: FlashMethod? = null + var imageLocation: ImageLocation? = null + var streamingWrite: Boolean = false + var imageFile: Uri? = null +} \ No newline at end of file diff --git a/app/src/main/java/eu/depau/ddroid/abc/WizardActivity.kt b/app/src/main/java/eu/depau/ddroid/abc/WizardActivity.kt new file mode 100644 index 0000000..536bca3 --- /dev/null +++ b/app/src/main/java/eu/depau/ddroid/abc/WizardActivity.kt @@ -0,0 +1,34 @@ +package eu.depau.ddroid.abc + +import android.content.Intent +import android.support.v7.app.AppCompatActivity +import android.view.View +import eu.depau.ddroid.StateKeeper + +abstract class WizardActivity : AppCompatActivity() { + abstract fun goToNewFragment(fragment: WizardFragment) + + open fun onCheckBoxClicked(view: View) { + StateKeeper.currentFragment?.onCheckBoxClicked(view) + } + + open fun onButtonClicked(view: View) { + StateKeeper.currentFragment?.onButtonClicked(view) + } + + open fun onRadioButtonClicked(view: View) { + StateKeeper.currentFragment?.onRadioButtonClicked(view) + } + + open fun nextStep(view: View) { + StateKeeper.currentFragment?.nextStep(view) + } + + override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { + StateKeeper.currentFragment?.onRequestPermissionsResult(requestCode, permissions, grantResults) + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + StateKeeper.currentFragment?.onActivityResult(requestCode, resultCode, data) + } +} \ No newline at end of file diff --git a/app/src/main/java/eu/depau/ddroid/abc/WizardFragment.kt b/app/src/main/java/eu/depau/ddroid/abc/WizardFragment.kt new file mode 100644 index 0000000..2e12a0a --- /dev/null +++ b/app/src/main/java/eu/depau/ddroid/abc/WizardFragment.kt @@ -0,0 +1,16 @@ +package eu.depau.ddroid.abc + +import android.content.Intent +import android.support.v4.app.Fragment +import android.view.View + +abstract class WizardFragment : Fragment() { + abstract fun nextStep(view: View) + + open fun onFragmentAdded(activity: WizardActivity) {} + open fun onRadioButtonClicked(view: View) {} + open fun onCheckBoxClicked(view: View) {} + open override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {} + open fun onButtonClicked(view: View) {} + open override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) {} +} \ No newline at end of file diff --git a/app/src/main/java/eu/depau/ddroid/activities/MainActivity.kt b/app/src/main/java/eu/depau/ddroid/activities/MainActivity.kt new file mode 100644 index 0000000..44e7cc3 --- /dev/null +++ b/app/src/main/java/eu/depau/ddroid/activities/MainActivity.kt @@ -0,0 +1,51 @@ +package eu.depau.ddroid.activities + +import android.os.Bundle +import android.view.Menu +import android.view.MenuItem +import eu.depau.ddroid.R +import eu.depau.ddroid.abc.WizardActivity +import eu.depau.ddroid.abc.WizardFragment +import eu.depau.ddroid.fragments.FlashMethodFragment +import kotlinx.android.synthetic.main.activity_main.* + +class MainActivity : WizardActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + setSupportActionBar(toolbar) + fab.setOnClickListener(::nextStep) + + // Create new fragment and transaction + val fragment = FlashMethodFragment() + val transaction = supportFragmentManager.beginTransaction() + transaction.replace(R.id.fragment_layout, fragment) + transaction.commit() + fragment.onFragmentAdded(this) + } + + override fun goToNewFragment(fragment: WizardFragment) { + val transaction = supportFragmentManager.beginTransaction() + transaction.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left) + transaction.replace(R.id.fragment_layout, fragment) + transaction.addToBackStack(null) + transaction.commit() + fragment.onFragmentAdded(this) + } + + 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_settings -> true + else -> super.onOptionsItemSelected(item) + } + } +} diff --git a/app/src/main/java/eu/depau/ddroid/fragments/FlashMethodFragment.kt b/app/src/main/java/eu/depau/ddroid/fragments/FlashMethodFragment.kt new file mode 100644 index 0000000..3fea8a9 --- /dev/null +++ b/app/src/main/java/eu/depau/ddroid/fragments/FlashMethodFragment.kt @@ -0,0 +1,42 @@ +package eu.depau.ddroid.fragments + +import android.os.Bundle +import android.support.design.widget.Snackbar +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import eu.depau.ddroid.* +import eu.depau.ddroid.abc.WizardActivity +import eu.depau.ddroid.abc.WizardFragment +import eu.depau.ddroid.values.FlashMethod +import eu.depau.ddroid.values.WizardStep + +/** + * A placeholder fragment containing a simple view. + */ +class FlashMethodFragment : WizardFragment() { + override fun nextStep(view: View) { + if (StateKeeper.flashMethod == null) + Snackbar.make(view, "Please select writing method", Snackbar.LENGTH_LONG).show() + else + (activity as WizardActivity).goToNewFragment(ImageLocationFragment()) + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?): View? { + StateKeeper.currentFragment = this + StateKeeper.wizardStep = WizardStep.SELECT_FLASH_METHOD + + return inflater.inflate(R.layout.fragment_select_flash_method, container, false) + } + + override fun onRadioButtonClicked(view: View) { + StateKeeper.flashMethod = when (view.id) { + R.id.flash_dd_root_radio -> FlashMethod.FLASH_DD + R.id.flash_dd_usb_api_radio -> FlashMethod.FLASH_API + R.id.flash_unetbootin_radio -> FlashMethod.FLASH_UNETBOOTIN + R.id.flash_woeusb_radio -> FlashMethod.FLASH_WOEUSB + else -> null + } + } +} diff --git a/app/src/main/java/eu/depau/ddroid/fragments/ImageLocationFragment.kt b/app/src/main/java/eu/depau/ddroid/fragments/ImageLocationFragment.kt new file mode 100644 index 0000000..8db51f2 --- /dev/null +++ b/app/src/main/java/eu/depau/ddroid/fragments/ImageLocationFragment.kt @@ -0,0 +1,202 @@ +package eu.depau.ddroid.fragments + +import android.Manifest +import android.app.Activity +import android.content.Intent +import android.content.pm.PackageManager +import android.net.Uri +import android.os.Bundle +import android.provider.OpenableColumns +import android.support.design.widget.Snackbar +import android.support.v4.app.ActivityCompat +import android.support.v4.content.ContextCompat +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.Button +import android.widget.CheckBox +import android.widget.EditText +import eu.depau.ddroid.* +import eu.depau.ddroid.abc.WizardActivity +import eu.depau.ddroid.abc.WizardFragment +import eu.depau.ddroid.values.FlashMethod +import eu.depau.ddroid.values.ImageLocation +import eu.depau.ddroid.values.WizardStep + + +/** + * A placeholder fragment containing a simple view. + */ +class ImageLocationFragment : WizardFragment() { + val READ_REQUEST_CODE = 42 + val MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE = 29 + val TAG = "ImageLocationFragment" + + fun isStreamingAvailable(): Boolean { + if (StateKeeper.imageLocation != ImageLocation.REMOTE) + return false + if (StateKeeper.flashMethod != FlashMethod.FLASH_DD && StateKeeper.flashMethod != FlashMethod.FLASH_API) + return false + return true + } + + fun setStreamingCheckBoxAvailability(context: WizardActivity) { + val checkBox = context.findViewById(R.id.streaming_write_checkbox) + + if (checkBox == null) + return + + val curEnabled = checkBox.isEnabled + var enabled = isStreamingAvailable() + + if (curEnabled != enabled) { + checkBox.isEnabled = enabled + onCheckBoxClicked(checkBox) + } + } + + override fun onCheckBoxClicked(view: View) { + super.onCheckBoxClicked(view) + + if (view.id == R.id.streaming_write_checkbox) + StateKeeper.streamingWrite = view.isActivated && view.isEnabled + } + + override fun onRadioButtonClicked(view: View) { + StateKeeper.imageLocation = when (view.id) { + R.id.download_img_radio -> ImageLocation.REMOTE + R.id.use_local_img_radio -> ImageLocation.LOCAL + else -> null + } + + activity?.findViewById