Added App Introduction Screens

Added three screens explaining Meshtastic and how to use the app. This is only shown on the first launch of the app.
pull/460/head
Ayub 2022-08-10 17:12:49 +01:00
rodzic 4e2b00bfd5
commit 51f78a3328
11 zmienionych plików z 299 dodań i 199 usunięć

Wyświetl plik

@ -200,8 +200,15 @@ dependencies {
implementation "androidx.core:core-splashscreen:1.0.0-beta02"
implementation project(':geeksville-androidlib')
// App intro
implementation 'com.github.AppIntro:AppIntro:6.2.0'
}
kapt {
correctErrorTypes true
}
repositories {
maven { url "https://jitpack.io" }
}

Wyświetl plik

@ -1,196 +1,186 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.geeksville.mesh"
xmlns:tools="http://schemas.android.com/tools"
tools:ignore="GoogleAppIndexingWarning">
<!-- If a device is missing a GPS - we will still be able to work though , must be before uses-permission-->
<uses-feature
android:name="android.hardware.location"
android:required="false" />
<uses-feature
android:name="android.hardware.location.gps"
android:required="false" />
<!-- TODO - wait for targetSdkVersion 31
&lt;!&ndash; Request legacy Bluetooth permissions on older devices &ndash;&gt;
<uses-permission android:name="android.permission.BLUETOOTH"
android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"
android:maxSdkVersion="30" />
&lt;!&ndash; API 31+ Bluetooth permissions &ndash;&gt;
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN"
android:usesPermissionFlags="neverForLocation" />
-->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<!-- Permissions required for providing location (from phone GPS) to mesh -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<!-- This permission is required for analytics - and soon the MQTT gateway -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!--
This permission is optional but recommended so we can be smart
about when to send data.
-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- Only for debug log writing, disable for production
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-->
<!-- We run our mesh code as a foreground service - FIXME, find a way to stop doing this -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<!-- Needed to open our bluetooth connection to our paired device (after reboot) -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<!-- For android >=26 we can use the new BLE scanning API, which allows auto launching our service when our device is seen -->
<uses-permission android:name="android.permission.REQUEST_COMPANION_RUN_IN_BACKGROUND" />
<uses-permission android:name="android.permission.REQUEST_COMPANION_USE_DATA_IN_BACKGROUND" />
<!-- Uart access -->
<!-- zxing library for QR Code scanning using camera -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature
android:name="android.hardware.bluetooth_le"
android:required="false" />
<!-- For the modern BLE scanning API -->
<uses-feature
android:name="android.software.companion_device_setup"
android:required="false" />
<!-- for USB serial access -->
<uses-feature
android:name="android.hardware.usb.host"
android:required="false" />
<!-- hardware acceleration is required for zxing barcode lib -->
<application
tools:replace="android:icon"
android:name="com.geeksville.mesh.MeshUtilApplication"
android:allowBackup="false"
android:icon="@mipmap/ic_launcher2"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher2_round"
android:supportsRtl="true"
android:hardwareAccelerated="true"
android:theme="@style/AppTheme">
<meta-data
android:name="com.mixpanel.android.MPConfig.DisableViewCrawler"
android:value="true" />
<!-- Default crash collection and analytics off until we (possibly) turn it on in application.onCreate -->
<meta-data
android:name="firebase_crashlytics_collection_enabled"
android:value="false" />
<meta-data
android:name="firebase_analytics_collection_enabled"
android:value="false" />
<meta-data
android:name="com.google.mlkit.vision.DEPENDENCIES"
android:value="barcode_ui"/>
<!-- we need bind job service for oreo -->
<service
android:name="com.geeksville.mesh.service.SoftwareUpdateService"
android:enabled="true"
android:exported="false"
android:permission="android.permission.BIND_JOB_SERVICE" />
<!-- This is the public API for doing mesh radio operations from android apps -->
<service
android:name="com.geeksville.mesh.service.MeshService"
android:enabled="true"
android:exported="true" tools:ignore="ExportedActivity">
<intent-filter>
<action android:name="com.geeksville.mesh.Service" />
</intent-filter>
</service>
<!-- zxing for QR Code scanning: lock portrait orientation -->
<activity
android:name="com.journeyapps.barcodescanner.CaptureActivity"
android:screenOrientation="portrait"
tools:replace="screenOrientation" />
<activity
android:name="com.geeksville.mesh.MainActivity"
android:launchMode="singleInstance"
android:screenOrientation="portrait"
android:windowSoftInputMode="stateAlwaysHidden"
android:theme="@style/Theme.App.Starting"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter android:autoVerify="true">
<!-- The QR codes to share channel settings are shared as meshtastic URLS
an approximate example:
http://www.meshtastic.org/d/YXNkZnF3ZXJhc2RmcXdlcmFzZGZxd2Vy
-->
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="https"
android:host="www.meshtastic.org"
android:pathPrefix="/d/" />
<data
android:scheme="https"
android:host="www.meshtastic.org"
android:pathPrefix="/D/" />
</intent-filter>
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
<!-- The USB devices we want to be informed about -->
<meta-data
android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource="@xml/device_filter" />
</activity>
<receiver android:name="com.geeksville.mesh.service.BootCompleteReceiver"
android:exported="false">
<!-- handle boot events -->
<intent-filter>
<category android:name="android.intent.category.DEFAULT" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
<!--For HTC devices per https://stackoverflow.com/questions/20441308/boot-completed-not-working-android/46294732#46294732 -->
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON" />
<!-- for testing -->
<action android:name="com.geeksville.mesh.SIM_BOOT" />
</intent-filter>
<!-- Also restart our service if the app gets upgraded -->
<intent-filter>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
<!-- I was using PACKAGE_REPLACED, but MY_PACKAGE_REPLACED is newer and seems cleaner
<data
android:scheme="package"
android:path="com.geeksville.mesh" /> -->
</intent-filter>
</receiver>
</application>
</manifest>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.geeksville.mesh"
tools:ignore="GoogleAppIndexingWarning">
<!-- If a device is missing a GPS - we will still be able to work though , must be before uses-permission -->
<uses-feature
android:name="android.hardware.location"
android:required="false" />
<uses-feature
android:name="android.hardware.location.gps"
android:required="false" />
<!--
TODO - wait for targetSdkVersion 31
&lt;!&ndash; Request legacy Bluetooth permissions on older devices &ndash;&gt;
<uses-permission android:name="android.permission.BLUETOOTH"
android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"
android:maxSdkVersion="30" />
&lt;!&ndash; API 31+ Bluetooth permissions &ndash;&gt;
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN"
android:usesPermissionFlags="neverForLocation" />
-->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <!-- Permissions required for providing location (from phone GPS) to mesh -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" /> <!-- This permission is required for analytics - and soon the MQTT gateway -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!--
This permission is optional but recommended so we can be smart
about when to send data.
-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!--
Only for debug log writing, disable for production
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-->
<!-- We run our mesh code as a foreground service - FIXME, find a way to stop doing this -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <!-- Needed to open our bluetooth connection to our paired device (after reboot) -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <!-- For android >=26 we can use the new BLE scanning API, which allows auto launching our service when our device is seen -->
<uses-permission android:name="android.permission.REQUEST_COMPANION_RUN_IN_BACKGROUND" />
<uses-permission android:name="android.permission.REQUEST_COMPANION_USE_DATA_IN_BACKGROUND" /> <!-- Uart access -->
<!-- zxing library for QR Code scanning using camera -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature
android:name="android.hardware.bluetooth_le"
android:required="false" /> <!-- For the modern BLE scanning API -->
<uses-feature
android:name="android.software.companion_device_setup"
android:required="false" /> <!-- for USB serial access -->
<uses-feature
android:name="android.hardware.usb.host"
android:required="false" />
<application
android:name=".MeshUtilApplication"
android:allowBackup="false"
android:hardwareAccelerated="true"
android:icon="@mipmap/ic_launcher2"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher2_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
tools:replace="android:icon">
<activity
android:name=".AppIntroduction"
android:label="Meshtastic">
<!--
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
-->
</activity>
<meta-data
android:name="com.mixpanel.android.MPConfig.DisableViewCrawler"
android:value="true" /> <!-- Default crash collection and analytics off until we (possibly) turn it on in application.onCreate -->
<meta-data
android:name="firebase_crashlytics_collection_enabled"
android:value="false" />
<meta-data
android:name="firebase_analytics_collection_enabled"
android:value="false" />
<meta-data
android:name="com.google.mlkit.vision.DEPENDENCIES"
android:value="barcode_ui" /> <!-- we need bind job service for oreo -->
<service
android:name=".service.SoftwareUpdateService"
android:enabled="true"
android:exported="false"
android:permission="android.permission.BIND_JOB_SERVICE" /> <!-- This is the public API for doing mesh radio operations from android apps -->
<service
android:name=".service.MeshService"
android:enabled="true"
android:exported="true"
tools:ignore="ExportedActivity">
<intent-filter>
<action android:name="com.geeksville.mesh.Service" />
</intent-filter>
</service> <!-- zxing for QR Code scanning: lock portrait orientation -->
<activity
android:name="com.journeyapps.barcodescanner.CaptureActivity"
android:screenOrientation="portrait"
tools:replace="screenOrientation" />
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleInstance"
android:screenOrientation="portrait"
android:theme="@style/Theme.App.Starting"
android:windowSoftInputMode="stateAlwaysHidden">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter android:autoVerify="true">
<!--
The QR codes to share channel settings are shared as meshtastic URLS
an approximate example:
http://www.meshtastic.org/d/YXNkZnF3ZXJhc2RmcXdlcmFzZGZxd2Vy
-->
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="www.meshtastic.org"
android:pathPrefix="/d/"
android:scheme="https" />
<data
android:host="www.meshtastic.org"
android:pathPrefix="/D/"
android:scheme="https" />
</intent-filter>
<intent-filter>
<action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
</intent-filter>
<!-- The USB devices we want to be informed about -->
<meta-data
android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource="@xml/device_filter" />
</activity>
<receiver
android:name=".service.BootCompleteReceiver"
android:exported="false">
<!-- handle boot events -->
<intent-filter>
<category android:name="android.intent.category.DEFAULT" />
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
<!-- For HTC devices per https://stackoverflow.com/questions/20441308/boot-completed-not-working-android/46294732#46294732 -->
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON" />
<!-- for testing -->
<action android:name="com.geeksville.mesh.SIM_BOOT" />
</intent-filter>
<!-- Also restart our service if the app gets upgraded -->
<intent-filter>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
<!--
I was using PACKAGE_REPLACED, but MY_PACKAGE_REPLACED is newer and seems cleaner
<data
android:scheme="package"
android:path="com.geeksville.mesh" />
-->
</intent-filter>
</receiver>
</application>
</manifest>

Wyświetl plik

@ -0,0 +1,68 @@
package com.geeksville.mesh
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.os.Bundle
import androidx.fragment.app.Fragment
import com.github.appintro.AppIntro
import com.github.appintro.AppIntroFragment
class AppIntroduction : AppIntro() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Make sure you don't call setContentView!
// Call addSlide passing your Fragments.
// You can use AppIntroFragment to use a pre-built fragment
addSlide(
AppIntroFragment.createInstance(
title = resources.getString(R.string.intro_welcome_title),
description = resources.getString(R.string.intro_meshtastic_desc),
imageDrawable = R.mipmap.ic_launcher2_round,
backgroundColorRes = R.color.colourGrey,
descriptionColorRes = R.color.colorOnPrimary
))
addSlide(AppIntroFragment.createInstance(
title = resources.getString(R.string.intro_get_started),
description = resources.getString(R.string.intro_started_text),
imageDrawable = R.drawable.icon_meanings,
backgroundColorRes = R.color.colourGrey,
descriptionColorRes = R.color.colorOnPrimary
))
addSlide(AppIntroFragment.createInstance(
title = resources.getString(R.string.intro_ecryption_title),
description = resources.getString(R.string.intro_encryption_text),
imageDrawable = R.drawable.channel_name_image,
backgroundColorRes = R.color.colourGrey,
descriptionColorRes = R.color.colorOnPrimary
))
//addSlide(SlideTwoFragment())
}
override fun onSkipPressed(currentFragment: Fragment?) {
super.onSkipPressed(currentFragment)
// Decide what to do when the user clicks on "Skip"
finish()
val preferences = getSharedPreferences("PREFERENCES", Context.MODE_PRIVATE)
var editor = preferences.edit()
editor.putBoolean("app_intro_completed", true)
editor.apply()
startActivity(Intent(this, MainActivity::class.java))
}
override fun onDonePressed(currentFragment: Fragment?) {
super.onDonePressed(currentFragment)
// Decide what to do when the user clicks on "Done"
finish()
val preferences = getSharedPreferences("PREFERENCES", Context.MODE_PRIVATE)
var editor = preferences.edit()
editor.putBoolean("app_intro_completed", true)
editor.apply()
startActivity(Intent(this, MainActivity::class.java))
}
}

Wyświetl plik

@ -404,9 +404,16 @@ class MainActivity : BaseActivity(), Logging,
}
override fun onCreate(savedInstanceState: Bundle?) {
val preferences = getSharedPreferences("PREFERENCES", Context.MODE_PRIVATE)
installSplashScreen()
super.onCreate(savedInstanceState)
if (preferences.getBoolean("app_intro_completed", false) == false) {
startActivity(Intent(this, AppIntroduction::class.java))
}
binding = ActivityMainBinding.inflate(layoutInflater)
val prefs = UIViewModel.getPreferences(this)
@ -1070,6 +1077,10 @@ class MainActivity : BaseActivity(), Logging,
chooseMapStyle()
return true
}
R.id.show_intro -> {
startActivity(Intent(this, AppIntroduction::class.java))
return true
}
else -> super.onOptionsItemSelected(item)
}
}

Wyświetl plik

@ -21,9 +21,11 @@ val Context.bluetoothManager: BluetoothManager? get() = getSystemService(Context
val Context.deviceManager: CompanionDeviceManager?
@SuppressLint("InlinedApi")
get() {
val activity: MainActivity? = GeeksvilleApplication.currentActivity as MainActivity?
return if (hasCompanionDeviceApi()) activity?.getSystemService(Context.COMPANION_DEVICE_SERVICE) as? CompanionDeviceManager?
else null
if (GeeksvilleApplication.currentActivity is MainActivity) {
val activity = GeeksvilleApplication.currentActivity
if (hasCompanionDeviceApi()) return activity?.getSystemService(Context.COMPANION_DEVICE_SERVICE) as? CompanionDeviceManager?
}
return null
}
val Context.usbManager: UsbManager get() = requireNotNull(getSystemService(Context.USB_SERVICE) as? UsbManager?) { "USB_SERVICE is not available"}

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 194 KiB

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 52 KiB

Wyświetl plik

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".AppIntroduction">
</androidx.constraintlayout.widget.ConstraintLayout>

Wyświetl plik

@ -36,6 +36,10 @@
android:id="@+id/preferences_map_style"
android:title="@string/preferences_map_style"
app:showAsAction="withText" />
<item
android:id="@+id/show_intro"
android:title="@string/show_intro"
app:showAsAction="withText" />
<item
android:id="@+id/about"
android:title="@string/about"

Wyświetl plik

@ -12,4 +12,5 @@
<color name="selectedColor">#67EA94</color>
<color name="unselectedColor">#212121</color>
<color name="buttonColor">#67EA94</color>
<color name="colourGrey">#535353</color>
</resources>

Wyświetl plik

@ -144,4 +144,13 @@
<string name="resend">Resend</string>
<string name="shutdown">Shutdown</string>
<string name="reboot">Reboot</string>
<!-- TODO: Remove or change this placeholder text -->
<string name="hello_blank_fragment">Hello blank fragment</string>
<string name="show_intro">Show Introduction</string>
<string name="intro_welcome_title">Welcome to Meshtastic</string>
<string name="intro_meshtastic_desc">Meshtastic is an open-source, off-grid, encrypted communication platform. The meshtastic radios form a mesh network and communicate using the LoRa protocol to send text messages</string>
<string name="intro_get_started">...Let\'s get started!</string>
<string name="intro_started_text">Connect your meshtastic device by using either bluetooth or serial. \n\nYou may need to wake your node if they are battery powered. \n\nYou can see which devices are compatible at www.meshtastic.org/docs/hardware</string>
<string name="intro_ecryption_title">"Setting up encryption"</string>
<string name="intro_encryption_text">To enable encryption, go to the channel tab and change the channel name. This will set a random key and enable AES256 encryption. \n\nTo communicate with other devices they will need to scan your QR code or follow the shared link to configure the channel settings.</string>
</resources>