diff --git a/app/build.gradle b/app/build.gradle index 1af9535cdfd5a33802732072fac76b0aada1417a..60adf86bbf4cf3a067aa4fea983fcb426b8e2f9a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -4,6 +4,8 @@ apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' +apply plugin: 'androidx.navigation.safeargs.kotlin' + android { compileSdkVersion 29 buildToolsVersion "29.0.1" @@ -40,4 +42,7 @@ dependencies { implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0' implementation 'androidx.work:work-runtime-ktx:2.2.0' implementation 'org.apache.commons:commons-compress:1.18' + implementation "androidx.navigation:navigation-fragment-ktx:$nav_version" + implementation "androidx.navigation:navigation-ui-ktx:$nav_version" + } diff --git a/app/src/main/java/de/ccc/events/badge/card10/MainActivity.kt b/app/src/main/java/de/ccc/events/badge/card10/MainActivity.kt index 7adb2066aaa25c53bcba0042d21215f0d63efca0..64f9ef1c93418dc8b07c291a94a6fea4cd326b28 100644 --- a/app/src/main/java/de/ccc/events/badge/card10/MainActivity.kt +++ b/app/src/main/java/de/ccc/events/badge/card10/MainActivity.kt @@ -31,6 +31,8 @@ import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat +import androidx.navigation.NavController +import androidx.navigation.findNavController import androidx.work.ExistingPeriodicWorkPolicy import androidx.work.PeriodicWorkRequestBuilder import androidx.work.WorkManager @@ -95,15 +97,6 @@ class MainActivity : AppCompatActivity() { } fun permissionGranted() { - val fragment = when { - intent.action == "application/x.card10.app" -> InstallerFragment() - else -> MainFragment() - } - - supportFragmentManager.beginTransaction() - .replace(R.id.fragment_container, fragment) - .commit() - // val workManager = WorkManager.getInstance(this) // if (!bluetoothAdapter.bondedDevices.isEmpty() // ) { @@ -116,4 +109,10 @@ class MainActivity : AppCompatActivity() { // workManager.cancelUniqueWork(WORK_NAME) // } } + + override fun onBackPressed() { + if (!findNavController(R.id.nav_host_fragment).popBackStack()) { + super.onBackPressed() + } + } } diff --git a/app/src/main/java/de/ccc/events/badge/card10/common/ConnectionService.kt b/app/src/main/java/de/ccc/events/badge/card10/common/ConnectionService.kt index 011096c874ea9ba3a3534fe4e353c11ec38a6199..6215005026a4c4497bdbeda0cadfa94b801a7645 100644 --- a/app/src/main/java/de/ccc/events/badge/card10/common/ConnectionService.kt +++ b/app/src/main/java/de/ccc/events/badge/card10/common/ConnectionService.kt @@ -31,8 +31,6 @@ import de.ccc.events.badge.card10.FILE_SERVICE_UUID import de.ccc.events.badge.card10.R import de.ccc.events.badge.card10.filetransfer.LowEffortService import de.ccc.events.badge.card10.time.Card10Service -import java.lang.IllegalStateException -import java.lang.NullPointerException import java.util.* private const val TAG = "ConnectionService" diff --git a/app/src/main/java/de/ccc/events/badge/card10/filetransfer/BatchTransferFragment.kt b/app/src/main/java/de/ccc/events/badge/card10/filetransfer/BatchTransferFragment.kt index 801b7ca4dfc367b99738025acb9ee37b11d265b7..16d8eabfd422a0d4e160157b485c93edbb00a159 100644 --- a/app/src/main/java/de/ccc/events/badge/card10/filetransfer/BatchTransferFragment.kt +++ b/app/src/main/java/de/ccc/events/badge/card10/filetransfer/BatchTransferFragment.kt @@ -22,21 +22,17 @@ package de.ccc.events.badge.card10.filetransfer -import android.bluetooth.BluetoothGatt -import android.net.Uri import android.os.Bundle import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment +import androidx.navigation.fragment.findNavController import de.ccc.events.badge.card10.R import de.ccc.events.badge.card10.common.ConnectionService import de.ccc.events.badge.card10.common.GattListener -import de.ccc.events.badge.card10.main.MainFragment import kotlinx.android.synthetic.main.batch_transfer_fragment.* -import java.lang.Exception -import java.lang.IllegalStateException private const val TAG = "BatchTransferFragment" @@ -47,9 +43,7 @@ class BatchTransferFragment : Fragment(), FileTransferListener, GattListener { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - - val args = arguments ?: throw IllegalStateException() - val jobs = args.get("jobs") as? Array ?: throw IllegalStateException() + val jobs = BatchTransferFragmentArgs.fromBundle(requireArguments()).jobs queue = TransferQueue(jobs) } @@ -64,11 +58,7 @@ class BatchTransferFragment : Fragment(), FileTransferListener, GattListener { } button_done.setOnClickListener { - val fragment = MainFragment() - fragmentManager!!.beginTransaction() - .replace(R.id.fragment_container, fragment) - .addToBackStack(null) - .commit() + findNavController().popBackStack() } startTransfer() @@ -108,7 +98,7 @@ class BatchTransferFragment : Fragment(), FileTransferListener, GattListener { val ctx = activity ?: throw IllegalStateException() val reader = ChunkedReader(ctx, transferJob.sourceUri, ConnectionService.mtu) val service = ConnectionService.leService ?: throw IllegalStateException() - transfer = FileTransfer(service, reader,this, transferJob.destPath) + transfer = FileTransfer(service, reader, this, transferJob.destPath) transfer?.start() } catch (e: Exception) { Log.e(TAG, "Failed to initialize transfer") diff --git a/app/src/main/java/de/ccc/events/badge/card10/filetransfer/FileTransferFragment.kt b/app/src/main/java/de/ccc/events/badge/card10/filetransfer/FileTransferFragment.kt index 8a196274886c175729358b8084fb343f52ebe561..d96d8b826ed8dbeb0ddee59c9bd9db8b4c4a0f1a 100644 --- a/app/src/main/java/de/ccc/events/badge/card10/filetransfer/FileTransferFragment.kt +++ b/app/src/main/java/de/ccc/events/badge/card10/filetransfer/FileTransferFragment.kt @@ -22,7 +22,6 @@ package de.ccc.events.badge.card10.filetransfer -import android.bluetooth.BluetoothAdapter import android.content.Intent import android.os.Bundle import android.util.Log @@ -33,17 +32,13 @@ import android.widget.Button import android.widget.EditText import android.widget.ProgressBar import android.widget.TextView -import androidx.annotation.UiThread import androidx.appcompat.app.AlertDialog import androidx.fragment.app.Fragment -import de.ccc.events.badge.card10.CARD10_BLUETOOTH_MAC_PREFIX +import androidx.navigation.fragment.findNavController import de.ccc.events.badge.card10.R import de.ccc.events.badge.card10.common.ConnectionException import de.ccc.events.badge.card10.common.ConnectionService import de.ccc.events.badge.card10.common.GattListener -import de.ccc.events.badge.card10.main.MainFragment -import java.lang.Exception -import java.lang.IllegalStateException private const val TAG = "FileTransferFragment" private const val INTENT_RESULT_CODE_FILE = 1 @@ -166,17 +161,14 @@ class FileTransferFragment : Fragment(), GattListener, FileTransferListener{ private fun showError(message: String?) { val ctx = context ?: throw IllegalStateException() - val fm = fragmentManager ?: throw IllegalStateException() + val controller = findNavController() val errorDialog = AlertDialog.Builder(ctx) .setMessage(message ?: getString(R.string.connection_error_generic)) .setPositiveButton(R.string.dialog_action_ok) { dialog, _ -> dialog.dismiss() - fm.beginTransaction() - .replace(R.id.fragment_container, MainFragment()) - .addToBackStack(null) - .commit() + controller.popBackStack() } .show() } diff --git a/app/src/main/java/de/ccc/events/badge/card10/hatchery/AppDetailFragment.kt b/app/src/main/java/de/ccc/events/badge/card10/hatchery/AppDetailFragment.kt index f741afa0730572b05bf641ec0a4d87f5b13d4af5..52aaa78a85b73bfaa62d41312a73ae8add8b5bcd 100644 --- a/app/src/main/java/de/ccc/events/badge/card10/hatchery/AppDetailFragment.kt +++ b/app/src/main/java/de/ccc/events/badge/card10/hatchery/AppDetailFragment.kt @@ -22,7 +22,6 @@ package de.ccc.events.badge.card10.hatchery -import android.net.Uri import android.os.AsyncTask import android.os.Bundle import android.util.Log @@ -32,10 +31,10 @@ import android.view.ViewGroup import androidx.appcompat.app.AlertDialog import androidx.core.net.toUri import androidx.fragment.app.Fragment -import androidx.fragment.app.FragmentManager +import androidx.navigation.NavController +import androidx.navigation.fragment.findNavController import de.ccc.events.badge.card10.R import de.ccc.events.badge.card10.common.LoadingDialog -import de.ccc.events.badge.card10.filetransfer.BatchTransferFragment import de.ccc.events.badge.card10.filetransfer.TransferJob import kotlinx.android.synthetic.main.app_detail_fragment.* import org.apache.commons.compress.archivers.tar.TarArchiveInputStream @@ -50,9 +49,8 @@ class AppDetailFragment : Fragment() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + app = AppDetailFragmentArgs.fromBundle(requireArguments()).app - val bundle = arguments ?: throw IllegalStateException() - app = bundle.getParcelable("app") ?: throw IllegalStateException() } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?) = @@ -69,7 +67,7 @@ class AppDetailFragment : Fragment() { val ctx = activity ?: throw java.lang.IllegalStateException() val loadingDialog = LoadingDialog() - loadingDialog.show(fragmentManager, "loading") + loadingDialog.show(requireFragmentManager(), "loading") val errorDialog = AlertDialog.Builder(ctx).setMessage(R.string.hatchery_error_generic) @@ -78,8 +76,8 @@ class AppDetailFragment : Fragment() { ) { dialog, _ -> dialog.dismiss() } .create() - val fm = fragmentManager ?: throw java.lang.IllegalStateException() - ReleaseDownload(app, ctx.cacheDir, loadingDialog, errorDialog, fm).execute() + val nav = findNavController(); + ReleaseDownload(app, ctx.cacheDir, loadingDialog, errorDialog, nav).execute() } } @@ -88,7 +86,7 @@ class AppDetailFragment : Fragment() { private val cacheDir: File, private val loadingDialog: LoadingDialog, private val errorDialog: AlertDialog, - private val fragmentManager: FragmentManager + private val navController: NavController ) : AsyncTask?>() { override fun doInBackground(vararg p0: Void?): List? { @@ -137,16 +135,9 @@ class AppDetailFragment : Fragment() { } loadingDialog.dismiss() + val nav = AppDetailFragmentDirections.startBatchTransfer(jobs.toTypedArray()) + navController.navigate(nav) - val bundle = Bundle() - bundle.putParcelableArray("jobs", jobs.toTypedArray()) - val fragment = BatchTransferFragment() - fragment.arguments = bundle - - fragmentManager.beginTransaction() - .replace(R.id.fragment_container, fragment) - .addToBackStack(null) - .commit() } fun createLauncher(slug: String, cacheDir: File): TransferJob { diff --git a/app/src/main/java/de/ccc/events/badge/card10/hatchery/AppListFragment.kt b/app/src/main/java/de/ccc/events/badge/card10/hatchery/AppListFragment.kt index cbf922ba2c3d7272ffbd6594edb66df8904de5e0..a09cec23077a4b9d7a9084b637fdff1c92e4c34c 100644 --- a/app/src/main/java/de/ccc/events/badge/card10/hatchery/AppListFragment.kt +++ b/app/src/main/java/de/ccc/events/badge/card10/hatchery/AppListFragment.kt @@ -30,6 +30,7 @@ import android.view.View import android.view.ViewGroup import androidx.appcompat.app.AlertDialog import androidx.fragment.app.Fragment +import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import de.ccc.events.badge.card10.R @@ -56,21 +57,12 @@ class AppListFragment : Fragment() { recyclerView.adapter = listAdapter val loadingDialog = LoadingDialog() - loadingDialog.show(fragmentManager, "loading") + loadingDialog.show(requireFragmentManager(), "loading") DownloadTask(activity as Context, listAdapter, loadingDialog).execute() } private fun onAppClicked(app: App) { - val bundle = Bundle() - bundle.putParcelable("app", app) - val fragment = AppDetailFragment() - fragment.arguments = bundle - - val fragmentManager = activity?.supportFragmentManager ?: throw IllegalStateException() - fragmentManager.beginTransaction() - .replace(R.id.fragment_container, fragment) - .addToBackStack(null) - .commit() + findNavController().navigate(AppListFragmentDirections.actionAppListFragmentToAppDetailFragment(app)) } private class DownloadTask( diff --git a/app/src/main/java/de/ccc/events/badge/card10/main/MainFragment.kt b/app/src/main/java/de/ccc/events/badge/card10/main/MainFragment.kt index fda341621ea15cda5d0403cbf3614e9ae8952553..93a46b3c58abc30517c4064f9d5e9098648209f1 100644 --- a/app/src/main/java/de/ccc/events/badge/card10/main/MainFragment.kt +++ b/app/src/main/java/de/ccc/events/badge/card10/main/MainFragment.kt @@ -27,41 +27,38 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.Button -import android.widget.TextView -import androidx.constraintlayout.widget.ConstraintLayout -import androidx.fragment.app.DialogFragment import androidx.fragment.app.Fragment +import androidx.navigation.fragment.findNavController import de.ccc.events.badge.card10.CARD10_BLUETOOTH_MAC_PREFIX import de.ccc.events.badge.card10.R import de.ccc.events.badge.card10.common.ConnectionService import de.ccc.events.badge.card10.common.GattListener -import de.ccc.events.badge.card10.filetransfer.FileTransferFragment -import de.ccc.events.badge.card10.hatchery.AppListFragment -import de.ccc.events.badge.card10.mood.MoodFragment -import de.ccc.events.badge.card10.scanner.ScannerFragment -import de.ccc.events.badge.card10.sparkle.BeautifulFragment import de.ccc.events.badge.card10.time.TimeUpdateDialog import kotlinx.android.synthetic.main.main_fragment.* -import java.lang.IllegalStateException -import java.sql.Connection class MainFragment : Fragment(), GattListener { private val bluetoothAdapter = BluetoothAdapter.getDefaultAdapter() - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?) = - inflater.inflate(R.layout.main_fragment, container, false) + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + if(activity!!.intent.action == "application/x.card10.app") { + findNavController().navigate(MainFragmentDirections.Installer()) + return null + } + return inflater.inflate(R.layout.main_fragment, container, false) + } + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - button_pair.setOnClickListener { startFragment(ScannerFragment()) } - button_mood.setOnClickListener { startFragment(MoodFragment()) } - button_beautiful.setOnClickListener { startFragment(BeautifulFragment()) } - button_hatchery.setOnClickListener { startFragment(AppListFragment()) } - button_send.setOnClickListener { startFragment(FileTransferFragment()) } + val con = findNavController() + button_pair.setOnClickListener { con.navigate(MainFragmentDirections.Scan()) } + button_mood.setOnClickListener { con.navigate(MainFragmentDirections.Mood()) } + button_beautiful.setOnClickListener { con.navigate(MainFragmentDirections.Beautiful()) } + button_hatchery.setOnClickListener { con.navigate(MainFragmentDirections.AppList()) } + button_send.setOnClickListener { con.navigate(MainFragmentDirections.Transfer()) } button_set_time.setOnClickListener { val dialogFragment = TimeUpdateDialog() - dialogFragment.show(fragmentManager, "time") + dialogFragment.show(fragmentManager!!, "time") dialogFragment.setTime() dialogFragment.dismiss() } @@ -81,12 +78,6 @@ class MainFragment : Fragment(), GattListener { } } - private fun startFragment(fragment: Fragment) { - fragmentManager!!.beginTransaction() - .replace(R.id.fragment_container, fragment) - .addToBackStack(null) - .commit() - } private fun showConnectedView() { activity?.runOnUiThread { diff --git a/app/src/main/java/de/ccc/events/badge/card10/mood/MoodFragment.kt b/app/src/main/java/de/ccc/events/badge/card10/mood/MoodFragment.kt index f9224c5e68a627da2225ad00f5a02aaa5accf3ba..130a0bec2ab9bdcc31a6651dab53cd130a8c88eb 100644 --- a/app/src/main/java/de/ccc/events/badge/card10/mood/MoodFragment.kt +++ b/app/src/main/java/de/ccc/events/badge/card10/mood/MoodFragment.kt @@ -32,6 +32,7 @@ import de.ccc.events.badge.card10.common.ConnectionService import de.ccc.events.badge.card10.time.Card10Service import kotlinx.android.synthetic.main.mood_fragment.* +@ExperimentalUnsignedTypes class MoodFragment : Fragment() { private var card10Service: Card10Service? = null diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 15057fc82dc01ad24c7dc55a4b324a43b41339ac..38a614ea0a153c53b0e73a584d188d81b691f2d6 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,5 +1,11 @@ - + + diff --git a/app/src/main/res/layout/disconnected_fragment.xml b/app/src/main/res/layout/disconnected_fragment.xml new file mode 100644 index 0000000000000000000000000000000000000000..1042893421edd904161c7a71d429ba694c29fec0 --- /dev/null +++ b/app/src/main/res/layout/disconnected_fragment.xml @@ -0,0 +1,42 @@ + + + + + + + + +