├── app ├── .gitignore ├── src │ └── main │ │ ├── res │ │ ├── xml │ │ │ ├── device_filter.xml │ │ │ └── root_preferences.xml │ │ ├── font │ │ │ └── gidolinya.otf │ │ ├── drawable-hdpi │ │ │ ├── ic_splash.png │ │ │ ├── ic_goggles.png │ │ │ ├── ic_goggles_white.png │ │ │ ├── ic_goggles_disconnected_red.png │ │ │ └── ic_goggles_disconnected_white.png │ │ ├── drawable-mdpi │ │ │ ├── ic_splash.png │ │ │ ├── ic_goggles.png │ │ │ ├── ic_goggles_white.png │ │ │ ├── ic_goggles_disconnected_red.png │ │ │ └── ic_goggles_disconnected_white.png │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ └── ic_launcher_foreground.png │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ └── ic_launcher_foreground.png │ │ ├── drawable-xhdpi │ │ │ ├── ic_goggles.png │ │ │ ├── ic_splash.png │ │ │ ├── ic_goggles_white.png │ │ │ ├── ic_goggles_disconnected_red.png │ │ │ └── ic_goggles_disconnected_white.png │ │ ├── drawable-xxhdpi │ │ │ ├── ic_goggles.png │ │ │ ├── ic_splash.png │ │ │ ├── ic_goggles_white.png │ │ │ ├── ic_goggles_disconnected_red.png │ │ │ ├── ic_goggles_disconnected_white.png │ │ │ └── ic_gogles_disconnected_white.png │ │ ├── drawable-xxxhdpi │ │ │ ├── ic_splash.png │ │ │ ├── ic_goggles.png │ │ │ ├── ic_goggles_white.png │ │ │ ├── ic_goggles_disconnected_red.png │ │ │ └── ic_goggles_disconnected_white.png │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ └── ic_launcher_foreground.png │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ └── ic_launcher_foreground.png │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ └── ic_launcher_foreground.png │ │ ├── layout │ │ │ ├── settings_activity.xml │ │ │ ├── activity_main.xml │ │ │ ├── datacollection_agreement_popup.xml │ │ │ └── backdrop_view.xml │ │ ├── drawable │ │ │ ├── splash.xml │ │ │ └── ic_launcher_background.xml │ │ ├── values │ │ │ ├── colors.xml │ │ │ ├── arrays.xml │ │ │ ├── themes.xml │ │ │ ├── styles.xml │ │ │ └── strings.xml │ │ ├── values-night │ │ │ └── themes.xml │ │ ├── drawable-v24 │ │ │ └── ic_launcher_foreground.xml │ │ ├── values-zh │ │ │ └── strings.xml │ │ ├── values-de │ │ │ └── strings.xml │ │ ├── values-es │ │ │ └── strings.xml │ │ ├── values-pt │ │ │ └── strings.xml │ │ └── values-fr │ │ │ └── strings.xml │ │ ├── ic_launcher_alpha-playstore.png │ │ ├── java │ │ ├── com │ │ │ └── fpvout │ │ │ │ └── digiview │ │ │ │ ├── OverlayStatus.java │ │ │ │ ├── UsbDeviceListener.java │ │ │ │ ├── VersionPreference.java │ │ │ │ ├── UsbDeviceBroadcastReceiver.java │ │ │ │ ├── OverlayView.java │ │ │ │ ├── SettingsActivity.java │ │ │ │ ├── UsbMaskConnection.java │ │ │ │ ├── DataCollectionAgreementPopupActivity.java │ │ │ │ ├── InputStreamDataSource.java │ │ │ │ ├── PerformancePreset.java │ │ │ │ ├── H264Extractor.java │ │ │ │ ├── InputStreamBufferedDataSource.java │ │ │ │ ├── VideoReaderExoplayer.java │ │ │ │ └── MainActivity.java │ │ └── usb │ │ │ ├── AndroidUSBOutputStream.java │ │ │ ├── AndroidUSBInputStream.java │ │ │ └── CircularByteBuffer.java │ │ └── AndroidManifest.xml ├── proguard-rules.pro └── build.gradle ├── settings.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .gitignore ├── .github └── workflows │ └── android.yml ├── LICENSE ├── gradle.properties ├── gradlew.bat ├── SupportedDevices.md ├── README.md └── gradlew /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | rootProject.name = "DigiView" -------------------------------------------------------------------------------- /app/src/main/res/xml/device_filter.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /app/src/main/res/font/gidolinya.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/res/font/gidolinya.otf -------------------------------------------------------------------------------- /app/src/main/ic_launcher_alpha-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/ic_launcher_alpha-playstore.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/res/drawable-hdpi/ic_splash.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/res/drawable-mdpi/ic_splash.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_goggles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/res/drawable-hdpi/ic_goggles.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_goggles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/res/drawable-mdpi/ic_goggles.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_goggles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/res/drawable-xhdpi/ic_goggles.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/res/drawable-xhdpi/ic_splash.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_goggles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/res/drawable-xxhdpi/ic_goggles.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/res/drawable-xxhdpi/ic_splash.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/res/drawable-xxxhdpi/ic_splash.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_goggles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/res/drawable-xxxhdpi/ic_goggles.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_goggles_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/res/drawable-hdpi/ic_goggles_white.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_goggles_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/res/drawable-mdpi/ic_goggles_white.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_goggles_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/res/drawable-xhdpi/ic_goggles_white.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_goggles_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/res/drawable-xxhdpi/ic_goggles_white.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_goggles_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/res/drawable-xxxhdpi/ic_goggles_white.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_goggles_disconnected_red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/res/drawable-hdpi/ic_goggles_disconnected_red.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_goggles_disconnected_red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/res/drawable-mdpi/ic_goggles_disconnected_red.png -------------------------------------------------------------------------------- /app/src/main/java/com/fpvout/digiview/OverlayStatus.java: -------------------------------------------------------------------------------- 1 | package com.fpvout.digiview; 2 | 3 | public enum OverlayStatus { 4 | Connected, 5 | Disconnected, 6 | Error 7 | } 8 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_goggles_disconnected_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/res/drawable-hdpi/ic_goggles_disconnected_white.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_goggles_disconnected_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/res/drawable-mdpi/ic_goggles_disconnected_white.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_goggles_disconnected_red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/res/drawable-xhdpi/ic_goggles_disconnected_red.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_goggles_disconnected_red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/res/drawable-xxhdpi/ic_goggles_disconnected_red.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_goggles_disconnected_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/res/drawable-xhdpi/ic_goggles_disconnected_white.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_goggles_disconnected_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/res/drawable-xxhdpi/ic_goggles_disconnected_white.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_gogles_disconnected_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/res/drawable-xxhdpi/ic_gogles_disconnected_white.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_goggles_disconnected_red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/res/drawable-xxxhdpi/ic_goggles_disconnected_red.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_goggles_disconnected_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fpvout/DigiView-Android/HEAD/app/src/main/res/drawable-xxxhdpi/ic_goggles_disconnected_white.png -------------------------------------------------------------------------------- /app/src/main/java/com/fpvout/digiview/UsbDeviceListener.java: -------------------------------------------------------------------------------- 1 | package com.fpvout.digiview; 2 | 3 | import android.hardware.usb.UsbDevice; 4 | 5 | public interface UsbDeviceListener { 6 | void usbDeviceApproved(UsbDevice device); 7 | void usbDeviceDetached(); 8 | } 9 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri May 21 03:24:22 CEST 2021 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .idea 11 | .DS_Store 12 | /build 13 | /captures 14 | .externalNativeBuild 15 | .cxx 16 | local.properties 17 | -------------------------------------------------------------------------------- /app/src/main/res/layout/settings_activity.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/splash.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FF000000 4 | #80000000 5 | #FFFFFFFF 6 | #4776e6 7 | #5A6CE6 8 | #8e54e9 9 | #7C5CE8 10 | -------------------------------------------------------------------------------- /app/src/main/res/values/arrays.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | @string/video_preset_default 5 | @string/video_preset_conservative 6 | @string/video_preset_aggressive 7 | @string/video_preset_legacy 8 | @string/video_preset_legacy_buffered 9 | 10 | 11 | 12 | default 13 | conservative 14 | aggressive 15 | legacy 16 | legacy_buffered 17 | 18 | -------------------------------------------------------------------------------- /.github/workflows/android.yml: -------------------------------------------------------------------------------- 1 | name: Android CI 2 | 3 | on: 4 | push: 5 | branches: [ master, dev ] 6 | pull_request: 7 | branches: [ master, dev ] 8 | workflow_dispatch: 9 | 10 | 11 | 12 | jobs: 13 | apk: 14 | name: Generate APK 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v1 19 | - name: set up JDK 1.8 20 | uses: actions/setup-java@v1 21 | with: 22 | java-version: 1.8 23 | - name: Build debug APK 24 | run: bash ./gradlew assembleDebug --stacktrace 25 | - name: Upload APK 26 | uses: actions/upload-artifact@v1 27 | with: 28 | name: app 29 | path: app/build/outputs/apk/debug/app-debug.apk 30 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 10 | 11 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/values-night/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/fpvout/digiview/VersionPreference.java: -------------------------------------------------------------------------------- 1 | package com.fpvout.digiview; 2 | 3 | import android.content.Context; 4 | import android.content.pm.PackageInfo; 5 | import android.content.pm.PackageManager; 6 | import android.util.AttributeSet; 7 | 8 | import androidx.preference.Preference; 9 | 10 | // From https://stackoverflow.com/a/20157577/877465 11 | public class VersionPreference extends Preference { 12 | public VersionPreference(Context context, AttributeSet attrs) { 13 | super(context, attrs); 14 | String versionName; 15 | final PackageManager packageManager = context.getPackageManager(); 16 | if (packageManager != null) { 17 | try { 18 | PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0); 19 | versionName = packageInfo.versionName; 20 | } catch (PackageManager.NameNotFoundException e) { 21 | versionName = null; 22 | } 23 | setSummary(versionName); 24 | } 25 | 26 | setSelectable(false); 27 | } 28 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 fpvout 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app"s APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Automatically convert third-party libraries to use AndroidX 19 | android.enableJetifier=true -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | 17 | 27 | -------------------------------------------------------------------------------- /app/src/main/java/com/fpvout/digiview/UsbDeviceBroadcastReceiver.java: -------------------------------------------------------------------------------- 1 | package com.fpvout.digiview; 2 | 3 | import android.content.BroadcastReceiver; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.hardware.usb.UsbDevice; 7 | import android.hardware.usb.UsbManager; 8 | 9 | public class UsbDeviceBroadcastReceiver extends BroadcastReceiver { 10 | private static final String ACTION_USB_PERMISSION = "com.fpvout.digiview.USB_PERMISSION"; 11 | private final UsbDeviceListener listener; 12 | 13 | public UsbDeviceBroadcastReceiver(UsbDeviceListener listener ){ 14 | this.listener = listener; 15 | } 16 | 17 | @Override 18 | public void onReceive(Context context, Intent intent) { 19 | String action = intent.getAction(); 20 | if (ACTION_USB_PERMISSION.equals(action)) { 21 | UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); 22 | 23 | if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) { 24 | if(device != null){ 25 | listener.usbDeviceApproved(device); 26 | } 27 | } 28 | } 29 | 30 | if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) { 31 | listener.usbDeviceDetached(); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/fpvout/digiview/OverlayView.java: -------------------------------------------------------------------------------- 1 | package com.fpvout.digiview; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.view.View; 6 | import android.widget.ImageView; 7 | import android.widget.TextView; 8 | 9 | import androidx.constraintlayout.widget.ConstraintLayout; 10 | 11 | public class OverlayView extends ConstraintLayout { 12 | private final TextView textView; 13 | private final ImageView imageView; 14 | 15 | public OverlayView(Context context, AttributeSet attrs) { 16 | super(context, attrs); 17 | 18 | inflate(getContext(),R.layout.backdrop_view,this); 19 | 20 | textView = findViewById(R.id.backdrop_text); 21 | 22 | imageView = findViewById(R.id.backdrop_image); 23 | } 24 | 25 | public void hide(){ 26 | setVisibility(View.GONE); 27 | } 28 | 29 | public void show(int textResourceId, OverlayStatus status){ 30 | showInfo(getContext().getString(textResourceId), status); 31 | } 32 | 33 | private void showInfo(String text, OverlayStatus status){ 34 | 35 | setVisibility(View.VISIBLE); 36 | 37 | textView.setText(text); 38 | 39 | int image = R.drawable.ic_goggles_white; 40 | switch(status){ 41 | case Disconnected: 42 | image = R.drawable.ic_goggles_disconnected_white; 43 | break; 44 | case Error: 45 | image = R.drawable.ic_goggles_disconnected_red; 46 | break; 47 | } 48 | 49 | imageView.setImageResource(image); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /app/src/main/java/com/fpvout/digiview/SettingsActivity.java: -------------------------------------------------------------------------------- 1 | package com.fpvout.digiview; 2 | 3 | import android.os.Bundle; 4 | import android.view.MenuItem; 5 | 6 | import androidx.annotation.NonNull; 7 | import androidx.appcompat.app.ActionBar; 8 | import androidx.appcompat.app.AppCompatActivity; 9 | import androidx.preference.PreferenceFragmentCompat; 10 | 11 | public class SettingsActivity extends AppCompatActivity { 12 | 13 | @Override 14 | protected void onCreate(Bundle savedInstanceState) { 15 | super.onCreate(savedInstanceState); 16 | setContentView(R.layout.settings_activity); 17 | if (savedInstanceState == null) { 18 | getSupportFragmentManager() 19 | .beginTransaction() 20 | .replace(R.id.settings, new SettingsFragment()) 21 | .commit(); 22 | } 23 | ActionBar actionBar = getSupportActionBar(); 24 | if (actionBar != null) { 25 | actionBar.setDisplayHomeAsUpEnabled(true); 26 | } 27 | } 28 | 29 | @Override 30 | public boolean onOptionsItemSelected(@NonNull MenuItem item) { 31 | 32 | if (item.getItemId() == android.R.id.home) { 33 | this.finish(); 34 | return true; 35 | } 36 | 37 | return super.onOptionsItemSelected(item); 38 | } 39 | 40 | public static class SettingsFragment extends PreferenceFragmentCompat { 41 | @Override 42 | public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { 43 | setPreferencesFromResource(R.xml.root_preferences, rootKey); 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/fpvout/digiview/UsbMaskConnection.java: -------------------------------------------------------------------------------- 1 | package com.fpvout.digiview; 2 | 3 | import android.hardware.usb.UsbDevice; 4 | import android.hardware.usb.UsbDeviceConnection; 5 | import android.hardware.usb.UsbInterface; 6 | 7 | import java.io.IOException; 8 | 9 | import usb.AndroidUSBInputStream; 10 | import usb.AndroidUSBOutputStream; 11 | 12 | public class UsbMaskConnection { 13 | 14 | private final byte[] magicPacket = "RMVT".getBytes(); 15 | private UsbDeviceConnection usbConnection; 16 | private UsbDevice device; 17 | private UsbInterface usbInterface; 18 | AndroidUSBInputStream mInputStream; 19 | AndroidUSBOutputStream mOutputStream; 20 | private boolean ready = false; 21 | 22 | public UsbMaskConnection() { 23 | } 24 | 25 | public void setUsbDevice(UsbDeviceConnection c, UsbDevice d) { 26 | usbConnection = c; 27 | device = d; 28 | usbInterface = device.getInterface(3); 29 | 30 | usbConnection.claimInterface(usbInterface,true); 31 | 32 | mOutputStream = new AndroidUSBOutputStream(usbInterface.getEndpoint(0), usbConnection); 33 | mInputStream = new AndroidUSBInputStream(usbInterface.getEndpoint(1), usbInterface.getEndpoint(0), usbConnection); 34 | ready = true; 35 | } 36 | 37 | public void start(){ 38 | mOutputStream.write(magicPacket); 39 | } 40 | 41 | public void stop() { 42 | ready = false; 43 | try { 44 | if (mInputStream != null) 45 | mInputStream.close(); 46 | 47 | if (mOutputStream != null) 48 | mOutputStream.close(); 49 | } catch (IOException e) { 50 | e.printStackTrace(); 51 | } 52 | 53 | if (usbConnection != null) { 54 | usbConnection.releaseInterface(usbInterface); 55 | usbConnection.close(); 56 | } 57 | } 58 | 59 | public boolean isReady() { 60 | return ready; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /app/src/main/java/com/fpvout/digiview/DataCollectionAgreementPopupActivity.java: -------------------------------------------------------------------------------- 1 | package com.fpvout.digiview; 2 | 3 | import android.app.AlertDialog; 4 | import android.content.Intent; 5 | import android.content.SharedPreferences; 6 | import android.os.Bundle; 7 | 8 | import androidx.appcompat.app.AppCompatActivity; 9 | import androidx.preference.PreferenceManager; 10 | 11 | public class DataCollectionAgreementPopupActivity extends AppCompatActivity { 12 | private SharedPreferences preferences; 13 | private AlertDialog.Builder builder; 14 | 15 | protected void onCreate(Bundle savedInstanceState) { 16 | super.onCreate(savedInstanceState); 17 | preferences = PreferenceManager.getDefaultSharedPreferences(this.getApplicationContext()); 18 | builder = new AlertDialog.Builder(this); 19 | initializeUI(); 20 | } 21 | 22 | private void initializeUI() { 23 | builder.setTitle(R.string.data_collection_header) 24 | .setMessage(R.string.data_collection_text) 25 | .setPositiveButton(R.string.data_collection_agree_button, (dialog, which) -> confirmDataCollection()) 26 | .setNegativeButton(R.string.data_collection_deny_button, (dialog, which) -> cancelDataCollection()); 27 | AlertDialog dialog = builder.create(); 28 | dialog.show(); 29 | } 30 | 31 | private void cancelDataCollection() { 32 | preferences.edit() 33 | .putBoolean("dataCollectionAccepted", false) 34 | .putBoolean("dataCollectionReplied", true).apply(); 35 | 36 | Intent intent = new Intent(); 37 | setResult(RESULT_OK, intent); 38 | 39 | finish(); 40 | } 41 | 42 | private void confirmDataCollection() { 43 | preferences.edit() 44 | .putBoolean("dataCollectionAccepted", true) 45 | .putBoolean("dataCollectionReplied", true).apply(); 46 | Intent intent = new Intent(); 47 | setResult(RESULT_OK, intent); 48 | finish(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/res/values-zh/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | DigiView\nfeed 4 | 等待USB设备… 5 | USB设备已批准 6 | USB设备已断开\n\n等待USB设备… 7 | 已发现USB设备. 8 | 等待视频… 9 | 数据收集协议 10 | 向DigiView团队报告崩溃数据? 11 | 该程序崩溃的次数可能比您炸机次数还少。\n 但即使发生崩溃,我们也想知道!\n\n我们使用Sentry跟踪错误并持续改进此应用程序。 12 | 拒绝 13 | 同意 14 | 设置 15 | 16 | 17 | 性能 18 | 隐私 19 | 视频预设 20 | 默认 21 | 保守 22 | 激进 23 | 传统 24 | 开启数据分析 25 | 隐私策略 26 | 查看我们收集数据的内容以及我们如何使用它们 27 | 视频播放器 28 | 全屏 29 | 也可以通过在视频播放器上点按两次或双指捏合来进行切换。 30 | 显示 DigiView 水印 31 | 相关链接 32 | 我们的网站 33 | 与我们和其他 DigiView 用户聊天 34 | DigiView Web应用 35 | 可以在Chrome以及基于Chromium核心的浏览器中使用,甚至可以在Android上运行! 36 | 我们所有的代码都是开源的 37 | 关于 38 | 应用程序版本 39 | 版权所有 40 | 开源证书 41 | MIT License 42 | 43 | 44 | -------------------------------------------------------------------------------- /app/src/main/java/com/fpvout/digiview/InputStreamDataSource.java: -------------------------------------------------------------------------------- 1 | package com.fpvout.digiview; 2 | 3 | import android.content.Context; 4 | import android.net.Uri; 5 | 6 | import com.google.android.exoplayer2.C; 7 | import com.google.android.exoplayer2.upstream.DataSource; 8 | import com.google.android.exoplayer2.upstream.DataSpec; 9 | import com.google.android.exoplayer2.upstream.TransferListener; 10 | 11 | import java.io.EOFException; 12 | import java.io.IOException; 13 | import java.io.InputStream; 14 | 15 | public class InputStreamDataSource implements DataSource { 16 | private Context context; 17 | private DataSpec dataSpec; 18 | private InputStream inputStream; 19 | private long bytesRemaining; 20 | private boolean opened; 21 | 22 | public InputStreamDataSource(Context context, DataSpec dataSpec, InputStream inputStream) { 23 | this.context = context; 24 | this.dataSpec = dataSpec; 25 | this.inputStream = inputStream; 26 | } 27 | 28 | @Override 29 | public void addTransferListener(TransferListener transferListener) { 30 | 31 | } 32 | 33 | @Override 34 | public long open(DataSpec dataSpec) throws IOException { 35 | try { 36 | long skipped = inputStream.skip(dataSpec.position); 37 | if (skipped < dataSpec.position) 38 | throw new EOFException(); 39 | 40 | if (dataSpec.length != C.LENGTH_UNSET) { 41 | bytesRemaining = dataSpec.length; 42 | } else { 43 | bytesRemaining = C.LENGTH_UNSET; 44 | } 45 | } catch (IOException e) { 46 | throw new IOException(e); 47 | } 48 | 49 | opened = true; 50 | return bytesRemaining; 51 | } 52 | 53 | @Override 54 | public int read(byte[] buffer, int offset, int readLength) throws IOException { 55 | return inputStream.read(buffer, offset, readLength); 56 | } 57 | 58 | @Override 59 | public Uri getUri() { 60 | return dataSpec.uri; 61 | } 62 | 63 | @Override 64 | public void close() throws IOException { 65 | try { 66 | if (inputStream != null) { 67 | inputStream.close(); 68 | } 69 | } catch (IOException e) { 70 | throw new IOException(e); 71 | } finally { 72 | inputStream = null; 73 | if (opened) { 74 | opened = false; 75 | } 76 | } 77 | } 78 | 79 | } -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 20 | 21 | 22 | 35 | 36 | 44 | 45 | 55 | 56 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /SupportedDevices.md: -------------------------------------------------------------------------------- 1 | | Brand | Model | Android Version | v1 Goggles | v2 Goggles | 25mbit | 50mbit | Latency | Notes | 2 | |:---------:|:--------------|:-----------------:|:-------------:|:-------------:|:---------:|:---------:|:---------:|:-----:| 3 | | Essential | PH-1 | 10 | 🟢 | ❔ | 🔴 | 🟢 | 200-2000ms|| 4 | | Fairphone | 3 | 10 | ❔ | 🟢 | 🟢 | ❔ | 5+ seconds|| 5 | | Google | Pixel 4XL | 11 | 🟢 | ❔ | ❔ | 🟢 | ~150ms || 6 | | Google | Nexus 7 (2012)| 7.1.2 | ❔ | 🟢 | 🟢 | 🟢 | ~1000+ms | Very high latency but still good enough to show spectators. | 7 | | Huawei | P30 Pro | 10.1 | 🟢 | ❔ | 🔴 | 🔴 | ❔ || 8 | | LG | Nexus 5x | 8.1 | ❔ | 🟢 | ❔ | 🟢 | 600+ms || 9 | | Nokia | 5.1 Plus | 10 | 🟢 | ❔ | 🟢 | 🟢 | ~200ms || 10 | | OnePlus | Nord N10 5G | 10 | 🟢 | ❔ | 🟢 | 🟢 | 100-200ms || 11 | | OnePlus | 8 Pro | 11 | ❔ | 🟢 | 🔴 | 🟢 | ~180ms || 12 | | OnePlus | 7T | 10 | 🟢 | ❔ | ❔ | 🟢 | ~150ms | Sometimes it works very well. Most of the times it shows a few frames at high speed and then freezes or shows frames at a very low rate. Changing cables didn't seem to help it.| 13 | | Samsung | Galaxy S20 | Latest | 🟢 | ❔ | 🔴 | 🟢 | Fast || 14 | | Samsung | S7 Edge | 8.0.0 | ❔ | 🟢 | ❔ | 🟢 | ~220ms || 15 | | Samsung | S20 5G | 11 | 🟢 | ❔ | 🔴 | 🟢 | 200-300ms || 16 | | Samsung | Galaxy S8 | ❔ | 🟢 | ❔ | ❔ | 🟢 | ❔ || 17 | | Samsung | Galaxy S9 | 10 | 🟢 | ❔ | ❔ | 🟢 | High, then low | Occasionally freezes 18 | | Samsung | Note 9 | 10 | 🟢 | ❔ | ❔ | 🟢 | ~150ms|| 19 | | Samsung | S10+ 5G | 11 | 🟢 | ❔ | 🟢 | 🟢 | ~500ms || 20 | | Samsung | Galaxy S7 (not edge)| 8.0.0 | ❔ | 🟢 | ❔ | 🟢 | ~200ms || 21 | | Samsung | S7 | 8.0 | 🟢 | ❔ | 🟢 | 🟢 | <1s|| 22 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 17 | 21 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 43 | 44 | 46 | 47 | 48 | 49 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /app/src/main/res/layout/datacollection_agreement_popup.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 14 | 15 |