Commit 68bdd85e authored by Anon's avatar Anon
Browse files

Merge branch 'navigation' into 'master'

RFC:Navigation

See merge request card10/companion-app-android!13
parents beb5b224 ee719399
...@@ -4,6 +4,8 @@ apply plugin: 'kotlin-android' ...@@ -4,6 +4,8 @@ apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions' apply plugin: 'kotlin-android-extensions'
apply plugin: 'androidx.navigation.safeargs.kotlin'
android { android {
compileSdkVersion 29 compileSdkVersion 29
buildToolsVersion "29.0.1" buildToolsVersion "29.0.1"
...@@ -40,4 +42,7 @@ dependencies { ...@@ -40,4 +42,7 @@ dependencies {
implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0' implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0'
implementation 'androidx.work:work-runtime-ktx:2.2.0' implementation 'androidx.work:work-runtime-ktx:2.2.0'
implementation 'org.apache.commons:commons-compress:1.18' implementation 'org.apache.commons:commons-compress:1.18'
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
} }
...@@ -31,6 +31,8 @@ import android.os.Bundle ...@@ -31,6 +31,8 @@ import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.navigation.NavController
import androidx.navigation.findNavController
import androidx.work.ExistingPeriodicWorkPolicy import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.PeriodicWorkRequestBuilder import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager import androidx.work.WorkManager
...@@ -95,15 +97,6 @@ class MainActivity : AppCompatActivity() { ...@@ -95,15 +97,6 @@ class MainActivity : AppCompatActivity() {
} }
fun permissionGranted() { 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) // val workManager = WorkManager.getInstance(this)
// if (!bluetoothAdapter.bondedDevices.isEmpty() // if (!bluetoothAdapter.bondedDevices.isEmpty()
// ) { // ) {
...@@ -116,4 +109,10 @@ class MainActivity : AppCompatActivity() { ...@@ -116,4 +109,10 @@ class MainActivity : AppCompatActivity() {
// workManager.cancelUniqueWork(WORK_NAME) // workManager.cancelUniqueWork(WORK_NAME)
// } // }
} }
override fun onBackPressed() {
if (!findNavController(R.id.nav_host_fragment).popBackStack()) {
super.onBackPressed()
}
}
} }
...@@ -31,8 +31,6 @@ import de.ccc.events.badge.card10.FILE_SERVICE_UUID ...@@ -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.R
import de.ccc.events.badge.card10.filetransfer.LowEffortService import de.ccc.events.badge.card10.filetransfer.LowEffortService
import de.ccc.events.badge.card10.time.Card10Service import de.ccc.events.badge.card10.time.Card10Service
import java.lang.IllegalStateException
import java.lang.NullPointerException
import java.util.* import java.util.*
private const val TAG = "ConnectionService" private const val TAG = "ConnectionService"
......
...@@ -22,21 +22,17 @@ ...@@ -22,21 +22,17 @@
package de.ccc.events.badge.card10.filetransfer package de.ccc.events.badge.card10.filetransfer
import android.bluetooth.BluetoothGatt
import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import de.ccc.events.badge.card10.R import de.ccc.events.badge.card10.R
import de.ccc.events.badge.card10.common.ConnectionService import de.ccc.events.badge.card10.common.ConnectionService
import de.ccc.events.badge.card10.common.GattListener 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 kotlinx.android.synthetic.main.batch_transfer_fragment.*
import java.lang.Exception
import java.lang.IllegalStateException
private const val TAG = "BatchTransferFragment" private const val TAG = "BatchTransferFragment"
...@@ -47,9 +43,7 @@ class BatchTransferFragment : Fragment(), FileTransferListener, GattListener { ...@@ -47,9 +43,7 @@ class BatchTransferFragment : Fragment(), FileTransferListener, GattListener {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
val jobs = BatchTransferFragmentArgs.fromBundle(requireArguments()).jobs
val args = arguments ?: throw IllegalStateException()
val jobs = args.get("jobs") as? Array<TransferJob> ?: throw IllegalStateException()
queue = TransferQueue(jobs) queue = TransferQueue(jobs)
} }
...@@ -64,11 +58,7 @@ class BatchTransferFragment : Fragment(), FileTransferListener, GattListener { ...@@ -64,11 +58,7 @@ class BatchTransferFragment : Fragment(), FileTransferListener, GattListener {
} }
button_done.setOnClickListener { button_done.setOnClickListener {
val fragment = MainFragment() findNavController().popBackStack()
fragmentManager!!.beginTransaction()
.replace(R.id.fragment_container, fragment)
.addToBackStack(null)
.commit()
} }
startTransfer() startTransfer()
...@@ -108,7 +98,7 @@ class BatchTransferFragment : Fragment(), FileTransferListener, GattListener { ...@@ -108,7 +98,7 @@ class BatchTransferFragment : Fragment(), FileTransferListener, GattListener {
val ctx = activity ?: throw IllegalStateException() val ctx = activity ?: throw IllegalStateException()
val reader = ChunkedReader(ctx, transferJob.sourceUri, ConnectionService.mtu) val reader = ChunkedReader(ctx, transferJob.sourceUri, ConnectionService.mtu)
val service = ConnectionService.leService ?: throw IllegalStateException() val service = ConnectionService.leService ?: throw IllegalStateException()
transfer = FileTransfer(service, reader,this, transferJob.destPath) transfer = FileTransfer(service, reader, this, transferJob.destPath)
transfer?.start() transfer?.start()
} catch (e: Exception) { } catch (e: Exception) {
Log.e(TAG, "Failed to initialize transfer") Log.e(TAG, "Failed to initialize transfer")
......
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
package de.ccc.events.badge.card10.filetransfer package de.ccc.events.badge.card10.filetransfer
import android.bluetooth.BluetoothAdapter
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
...@@ -33,17 +32,13 @@ import android.widget.Button ...@@ -33,17 +32,13 @@ import android.widget.Button
import android.widget.EditText import android.widget.EditText
import android.widget.ProgressBar import android.widget.ProgressBar
import android.widget.TextView import android.widget.TextView
import androidx.annotation.UiThread
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.Fragment 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.R
import de.ccc.events.badge.card10.common.ConnectionException import de.ccc.events.badge.card10.common.ConnectionException
import de.ccc.events.badge.card10.common.ConnectionService import de.ccc.events.badge.card10.common.ConnectionService
import de.ccc.events.badge.card10.common.GattListener 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 TAG = "FileTransferFragment"
private const val INTENT_RESULT_CODE_FILE = 1 private const val INTENT_RESULT_CODE_FILE = 1
...@@ -166,17 +161,14 @@ class FileTransferFragment : Fragment(), GattListener, FileTransferListener{ ...@@ -166,17 +161,14 @@ class FileTransferFragment : Fragment(), GattListener, FileTransferListener{
private fun showError(message: String?) { private fun showError(message: String?) {
val ctx = context ?: throw IllegalStateException() val ctx = context ?: throw IllegalStateException()
val fm = fragmentManager ?: throw IllegalStateException() val controller = findNavController()
val errorDialog = val errorDialog =
AlertDialog.Builder(ctx) AlertDialog.Builder(ctx)
.setMessage(message ?: getString(R.string.connection_error_generic)) .setMessage(message ?: getString(R.string.connection_error_generic))
.setPositiveButton(R.string.dialog_action_ok) { .setPositiveButton(R.string.dialog_action_ok) {
dialog, _ -> dialog.dismiss() dialog, _ -> dialog.dismiss()
fm.beginTransaction() controller.popBackStack()
.replace(R.id.fragment_container, MainFragment())
.addToBackStack(null)
.commit()
} }
.show() .show()
} }
......
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
package de.ccc.events.badge.card10.hatchery package de.ccc.events.badge.card10.hatchery
import android.net.Uri
import android.os.AsyncTask import android.os.AsyncTask
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
...@@ -32,10 +31,10 @@ import android.view.ViewGroup ...@@ -32,10 +31,10 @@ import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.core.net.toUri import androidx.core.net.toUri
import androidx.fragment.app.Fragment 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.R
import de.ccc.events.badge.card10.common.LoadingDialog 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 de.ccc.events.badge.card10.filetransfer.TransferJob
import kotlinx.android.synthetic.main.app_detail_fragment.* import kotlinx.android.synthetic.main.app_detail_fragment.*
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream import org.apache.commons.compress.archivers.tar.TarArchiveInputStream
...@@ -50,9 +49,8 @@ class AppDetailFragment : Fragment() { ...@@ -50,9 +49,8 @@ class AppDetailFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
app = AppDetailFragmentArgs.fromBundle(requireArguments()).app
val bundle = arguments ?: throw IllegalStateException()
app = bundle.getParcelable<App>("app") ?: throw IllegalStateException()
} }
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?) = override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?) =
...@@ -69,7 +67,7 @@ class AppDetailFragment : Fragment() { ...@@ -69,7 +67,7 @@ class AppDetailFragment : Fragment() {
val ctx = activity ?: throw java.lang.IllegalStateException() val ctx = activity ?: throw java.lang.IllegalStateException()
val loadingDialog = LoadingDialog() val loadingDialog = LoadingDialog()
loadingDialog.show(fragmentManager, "loading") loadingDialog.show(requireFragmentManager(), "loading")
val errorDialog = val errorDialog =
AlertDialog.Builder(ctx).setMessage(R.string.hatchery_error_generic) AlertDialog.Builder(ctx).setMessage(R.string.hatchery_error_generic)
...@@ -78,8 +76,8 @@ class AppDetailFragment : Fragment() { ...@@ -78,8 +76,8 @@ class AppDetailFragment : Fragment() {
) { dialog, _ -> dialog.dismiss() } ) { dialog, _ -> dialog.dismiss() }
.create() .create()
val fm = fragmentManager ?: throw java.lang.IllegalStateException() val nav = findNavController();
ReleaseDownload(app, ctx.cacheDir, loadingDialog, errorDialog, fm).execute() ReleaseDownload(app, ctx.cacheDir, loadingDialog, errorDialog, nav).execute()
} }
} }
...@@ -88,7 +86,7 @@ class AppDetailFragment : Fragment() { ...@@ -88,7 +86,7 @@ class AppDetailFragment : Fragment() {
private val cacheDir: File, private val cacheDir: File,
private val loadingDialog: LoadingDialog, private val loadingDialog: LoadingDialog,
private val errorDialog: AlertDialog, private val errorDialog: AlertDialog,
private val fragmentManager: FragmentManager private val navController: NavController
) : AsyncTask<Void, Void, List<TransferJob>?>() { ) : AsyncTask<Void, Void, List<TransferJob>?>() {
override fun doInBackground(vararg p0: Void?): List<TransferJob>? { override fun doInBackground(vararg p0: Void?): List<TransferJob>? {
...@@ -137,16 +135,9 @@ class AppDetailFragment : Fragment() { ...@@ -137,16 +135,9 @@ class AppDetailFragment : Fragment() {
} }
loadingDialog.dismiss() 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 { fun createLauncher(slug: String, cacheDir: File): TransferJob {
......
...@@ -30,6 +30,7 @@ import android.view.View ...@@ -30,6 +30,7 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import de.ccc.events.badge.card10.R import de.ccc.events.badge.card10.R
...@@ -56,21 +57,12 @@ class AppListFragment : Fragment() { ...@@ -56,21 +57,12 @@ class AppListFragment : Fragment() {
recyclerView.adapter = listAdapter recyclerView.adapter = listAdapter
val loadingDialog = LoadingDialog() val loadingDialog = LoadingDialog()
loadingDialog.show(fragmentManager, "loading") loadingDialog.show(requireFragmentManager(), "loading")
DownloadTask(activity as Context, listAdapter, loadingDialog).execute() DownloadTask(activity as Context, listAdapter, loadingDialog).execute()
} }
private fun onAppClicked(app: App) { private fun onAppClicked(app: App) {
val bundle = Bundle() findNavController().navigate(AppListFragmentDirections.actionAppListFragmentToAppDetailFragment(app))
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()
} }
private class DownloadTask( private class DownloadTask(
......
...@@ -27,41 +27,38 @@ import android.os.Bundle ...@@ -27,41 +27,38 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup 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.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import de.ccc.events.badge.card10.CARD10_BLUETOOTH_MAC_PREFIX import de.ccc.events.badge.card10.CARD10_BLUETOOTH_MAC_PREFIX
import de.ccc.events.badge.card10.R import de.ccc.events.badge.card10.R
import de.ccc.events.badge.card10.common.ConnectionService import de.ccc.events.badge.card10.common.ConnectionService
import de.ccc.events.badge.card10.common.GattListener 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 de.ccc.events.badge.card10.time.TimeUpdateDialog
import kotlinx.android.synthetic.main.main_fragment.* import kotlinx.android.synthetic.main.main_fragment.*
import java.lang.IllegalStateException
import java.sql.Connection
class MainFragment : Fragment(), GattListener { class MainFragment : Fragment(), GattListener {
private val bluetoothAdapter = BluetoothAdapter.getDefaultAdapter() private val bluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?) = override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
inflater.inflate(R.layout.main_fragment, container, false) 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?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
button_pair.setOnClickListener { startFragment(ScannerFragment()) } val con = findNavController()
button_mood.setOnClickListener { startFragment(MoodFragment()) } button_pair.setOnClickListener { con.navigate(MainFragmentDirections.Scan()) }
button_beautiful.setOnClickListener { startFragment(BeautifulFragment()) } button_mood.setOnClickListener { con.navigate(MainFragmentDirections.Mood()) }
button_hatchery.setOnClickListener { startFragment(AppListFragment()) } button_beautiful.setOnClickListener { con.navigate(MainFragmentDirections.Beautiful()) }
button_send.setOnClickListener { startFragment(FileTransferFragment()) } button_hatchery.setOnClickListener { con.navigate(MainFragmentDirections.AppList()) }
button_send.setOnClickListener { con.navigate(MainFragmentDirections.Transfer()) }
button_set_time.setOnClickListener { button_set_time.setOnClickListener {
val dialogFragment = TimeUpdateDialog() val dialogFragment = TimeUpdateDialog()
dialogFragment.show(fragmentManager, "time") dialogFragment.show(fragmentManager!!, "time")
dialogFragment.setTime() dialogFragment.setTime()
dialogFragment.dismiss() dialogFragment.dismiss()
} }
...@@ -81,12 +78,6 @@ class MainFragment : Fragment(), GattListener { ...@@ -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() { private fun showConnectedView() {
activity?.runOnUiThread { activity?.runOnUiThread {
......
...@@ -32,6 +32,7 @@ import de.ccc.events.badge.card10.common.ConnectionService ...@@ -32,6 +32,7 @@ import de.ccc.events.badge.card10.common.ConnectionService
import de.ccc.events.badge.card10.time.Card10Service import de.ccc.events.badge.card10.time.Card10Service
import kotlinx.android.synthetic.main.mood_fragment.* import kotlinx.android.synthetic.main.mood_fragment.*
@ExperimentalUnsignedTypes
class MoodFragment : Fragment() { class MoodFragment : Fragment() {
private var card10Service: Card10Service? = null private var card10Service: Card10Service? = null
......
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" <fragment
android:id="@+id/fragment_container" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent"/> android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph"/>
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/image_logo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/card10_logo_text"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/label_status"
android:layout_marginTop="@dimen/logo_margin_bottom"
android:gravity="center"
android:text="@string/main_label_not_connected"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/image_logo"/>
<androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="@+id/label_status"
app:layout_constraintBottom_toBottomOf="parent"
android:id="@+id/container_disconnected">
<Button android:id="@+id/button_pair"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/main_button_pair"
android:layout_marginTop="8dp"
style="@style/MainButton"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/nav_graph" app:startDestination="@id/mainFragment">
<fragment android:id="@+id/mainFragment" android:name="de.ccc.events.badge.card10.main.MainFragment"
android:label="MainFragment" tools:layout="@layout/main_fragment">
<action android:id="@+id/Mood" app:destination="@id/moodFragment"/>
<action android:id="@+id/Beautiful" app:destination="@id/beautifulFragment"/>
<action android:id="@+id/AppList" app:destination="@id/appListFragment"/>
<action android:id="@+id/Transfer"
app:destination="@id/fileTransferFragment"/>
<action android:id="@+id/Installer" app:destination="@id/installerFragment"/>