-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Starts adding a Screen Mirroring addon
- Loading branch information
Showing
40 changed files
with
1,429 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/build |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
plugins { | ||
id 'com.android.application' | ||
id 'kotlin-android' | ||
id 'kotlin-kapt' | ||
} | ||
|
||
repositories { | ||
maven { url 'https://jitpack.io' } | ||
} | ||
|
||
android { | ||
compileSdkVersion 30 | ||
buildToolsVersion "31.0.0" | ||
|
||
defaultConfig { | ||
applicationId "me.hufman.idriveconnectaddons.screen_mirror" | ||
minSdkVersion 23 | ||
targetSdkVersion 30 | ||
versionCode 1 | ||
versionName "1.0" | ||
|
||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" | ||
} | ||
|
||
buildFeatures { | ||
dataBinding true | ||
} | ||
buildTypes { | ||
release { | ||
minifyEnabled false | ||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' | ||
} | ||
} | ||
compileOptions { | ||
sourceCompatibility JavaVersion.VERSION_1_8 | ||
targetCompatibility JavaVersion.VERSION_1_8 | ||
} | ||
kotlinOptions { | ||
jvmTarget = '1.8' | ||
} | ||
} | ||
|
||
dependencies { | ||
|
||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" | ||
implementation 'androidx.core:core-ktx:1.6.0' | ||
implementation 'androidx.appcompat:appcompat:1.3.1' | ||
implementation 'com.google.android.material:material:1.4.0' | ||
implementation 'androidx.activity:activity-ktx:1.3.1' | ||
|
||
implementation 'io.bimmergestalt:IDriveConnectKit:jitpack_publish-SNAPSHOT' | ||
implementation 'io.bimmergestalt:IDriveConnectKitAndroid:jitpack_publish_2-SNAPSHOT' | ||
implementation project(path: ':lib') | ||
|
||
testImplementation 'junit:junit:4.+' | ||
androidTestImplementation 'androidx.test.ext:junit:1.1.3' | ||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# Add project specific ProGuard rules here. | ||
# You can control the set of applied configuration files using the | ||
# proguardFiles setting in build.gradle. | ||
# | ||
# For more details, see | ||
# http://developer.android.com/guide/developing/tools/proguard.html | ||
|
||
# If your project uses WebView with JS, uncomment the following | ||
# and specify the fully qualified class name to the JavaScript interface | ||
# class: | ||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview { | ||
# public *; | ||
#} | ||
|
||
# Uncomment this to preserve the line number information for | ||
# debugging stack traces. | ||
#-keepattributes SourceFile,LineNumberTable | ||
|
||
# If you keep the line number information, uncomment this to | ||
# hide the original source file name. | ||
#-renamesourcefileattribute SourceFile |
24 changes: 24 additions & 0 deletions
24
...oidTest/java/io/bimmergestalt/idriveconnectaddons/screenmirror/ExampleInstrumentedTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package io.bimmergestalt.idriveconnectaddons.screenmirror | ||
|
||
import androidx.test.platform.app.InstrumentationRegistry | ||
import androidx.test.ext.junit.runners.AndroidJUnit4 | ||
|
||
import org.junit.Test | ||
import org.junit.runner.RunWith | ||
|
||
import org.junit.Assert.* | ||
|
||
/** | ||
* Instrumented test, which will execute on an Android device. | ||
* | ||
* See [testing documentation](http://d.android.com/tools/testing). | ||
*/ | ||
@RunWith(AndroidJUnit4::class) | ||
class ExampleInstrumentedTest { | ||
@Test | ||
fun useAppContext() { | ||
// Context of the app under test. | ||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext | ||
assertEquals("me.hufman.idriveconnectaddons.screen_mirror", appContext.packageName) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" | ||
package="io.bimmergestalt.idriveconnectaddons.screenmirror"> | ||
|
||
<!-- Connect to local etch port --> | ||
<uses-permission android:name="android.permission.INTERNET" /> | ||
<!-- Provide a foreground service to indicate mirroring status --> | ||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> | ||
|
||
<application | ||
android:allowBackup="true" | ||
android:icon="@mipmap/ic_launcher" | ||
android:label="@string/app_name" | ||
android:roundIcon="@mipmap/ic_launcher_round" | ||
android:supportsRtl="true" | ||
android:theme="@style/Theme.IDriveConnectAddons"> | ||
<activity android:name=".MainActivity"> | ||
<intent-filter> | ||
<action android:name="android.intent.action.MAIN" /> | ||
</intent-filter> | ||
</activity> | ||
<activity android:name=".RequestActivity" /> | ||
<service android:name=".CarAppService"> | ||
<intent-filter> | ||
<action android:name="io.bimmergestalt.carconnection.service" /> | ||
</intent-filter> | ||
</service> | ||
<service android:name=".NotificationService" | ||
android:foregroundServiceType="mediaProjection" /> | ||
</application> | ||
|
||
</manifest> |
75 changes: 75 additions & 0 deletions
75
...r/src/main/java/io/bimmergestalt/idriveconnectaddons/screenmirror/CarAppAssetResources.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
package io.bimmergestalt.idriveconnectaddons.screenmirror | ||
|
||
import android.content.Context | ||
import io.bimmergestalt.idriveconnectkit.android.CarAppResources | ||
import io.bimmergestalt.idriveconnectkit.android.CertMangling | ||
import io.bimmergestalt.idriveconnectkit.android.security.SecurityAccess | ||
import java.io.ByteArrayInputStream | ||
import java.io.FileNotFoundException | ||
import java.io.InputStream | ||
|
||
/** | ||
* An implementation of CarAppResources for easy use in Android apps | ||
* | ||
* Loads resource files from the app context's assets | ||
* | ||
* It expects to find the App Certificate at: | ||
* - carapplications/$name/rhmi/$brand/$name.p7b | ||
* - carapplications/$name/$name.p7b | ||
* | ||
* It expects to find the ui_description.xml at: | ||
* - carapplications/$name/rhmi/$brand/ui_description.xml | ||
* - carapplications/$name/rhmi/common/ui_description.xml | ||
* - carapplications/$name/rhmi/ui_description.xml | ||
* | ||
* It expects to find the images.zip file at: | ||
* - carapplications/$name/rhmi/$brand/images.zip | ||
* - carapplications/$name/rhmi/common/images.zip | ||
* | ||
* It expects to find the textx.zip file at: | ||
* - carapplications/$name/rhmi/$brand/texts.zip | ||
* - carapplications/$name/rhmi/common/texts.zip | ||
* | ||
* The $brand is always lower-cased | ||
* | ||
* This module uses SecurityAccess to automatically alter the App Certificate | ||
* to include the necessary extra certs from the Security Module. | ||
* | ||
* todo: Move to IDriveConnectKitAndroid | ||
* */ | ||
class CarAppAssetResources(val context: Context, val name: String): CarAppResources { | ||
fun loadFile(path: String): InputStream? { | ||
try { | ||
return context.assets.open(path) | ||
} catch (e: FileNotFoundException) { | ||
return null | ||
} | ||
} | ||
|
||
fun getAppCertificateRaw(brand: String): InputStream? { | ||
return loadFile("carapplications/$name/rhmi/${brand.toLowerCase()}/$name.p7b") ?: | ||
loadFile("carapplications/$name/$name.p7b") | ||
} | ||
|
||
override fun getAppCertificate(brand: String): InputStream? { | ||
val appCert = getAppCertificateRaw(brand)?.readBytes() as ByteArray | ||
val signedCert = CertMangling.mergeBMWCert(appCert, SecurityAccess.getInstance(context).fetchBMWCerts(brandHint= brand)) | ||
return ByteArrayInputStream(signedCert) | ||
} | ||
|
||
override fun getUiDescription(brand: String): InputStream? { | ||
return loadFile("carapplications/$name/rhmi/${brand.toLowerCase()}/ui_description.xml") ?: | ||
loadFile("carapplications/$name/rhmi/common/ui_description.xml") ?: | ||
loadFile("carapplications/$name/rhmi/ui_description.xml") | ||
} | ||
|
||
override fun getImagesDB(brand: String): InputStream? { | ||
return loadFile("carapplications/$name/rhmi/${brand.toLowerCase()}/images.zip") ?: | ||
loadFile("carapplications/$name/rhmi/common/images.zip") | ||
} | ||
|
||
override fun getTextsDB(brand: String): InputStream? { | ||
return loadFile("carapplications/$name/rhmi/${brand.toLowerCase()}/texts.zip") ?: | ||
loadFile("carapplications/$name/rhmi/common/texts.zip") | ||
} | ||
} |
104 changes: 104 additions & 0 deletions
104
...n_mirror/src/main/java/io/bimmergestalt/idriveconnectaddons/screenmirror/CarAppService.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
package io.bimmergestalt.idriveconnectaddons.screenmirror | ||
|
||
import android.app.Service | ||
import android.content.Intent | ||
import android.os.Build | ||
import android.os.IBinder | ||
import android.util.Log | ||
import io.bimmergestalt.idriveconnectaddons.screenmirror.carapp.CarApp | ||
import io.bimmergestalt.idriveconnectkit.android.IDriveConnectionReceiver | ||
import io.bimmergestalt.idriveconnectkit.android.IDriveConnectionStatus | ||
import io.bimmergestalt.idriveconnectkit.android.security.SecurityAccess | ||
|
||
class CarAppService: Service() { | ||
var thread: CarThread? = null | ||
var app: CarApp? = null | ||
|
||
override fun onCreate() { | ||
super.onCreate() | ||
SecurityAccess.getInstance(applicationContext).connect() | ||
} | ||
|
||
/** | ||
* When a car is connected, it will bind the Addon Service | ||
*/ | ||
override fun onBind(intent: Intent?): IBinder? { | ||
intent ?: return null | ||
setConnection(intent) | ||
return null | ||
} | ||
|
||
/** | ||
* If the thread crashes for any reason, | ||
* opening the main app will trigger a Start on the Addon Services | ||
* as a chance to reconnect | ||
*/ | ||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { | ||
super.onStartCommand(intent, flags, startId) | ||
intent ?: return START_NOT_STICKY | ||
setConnection(intent) | ||
startThread() | ||
return START_STICKY | ||
} | ||
|
||
/** | ||
* The car has disconnected, so forget the previous details | ||
*/ | ||
override fun onUnbind(intent: Intent?): Boolean { | ||
IDriveConnectionStatus.reset() | ||
return super.onUnbind(intent) | ||
} | ||
|
||
/** | ||
* Parses the connection intent and sets the connection details | ||
* todo: Move to IDriveConnectionListener | ||
*/ | ||
fun setConnection(intent: Intent) { | ||
val brand = intent.getStringExtra("EXTRA_BRAND") | ||
val host = intent.getStringExtra("EXTRA_HOST") | ||
val port = intent.getIntExtra("EXTRA_PORT", -1) | ||
val instanceId = intent.getIntExtra("EXTRA_INSTANCE_ID", -1) | ||
Log.i(TAG, "Received connection details: $brand at $host:$port($instanceId)") | ||
brand ?: return | ||
host ?: return | ||
if (port == -1) { | ||
return | ||
} | ||
IDriveConnectionStatus.setConnection(brand, host, port, instanceId) | ||
startThread() | ||
} | ||
|
||
/** | ||
* Starts the thread for the car app, if it isn't running | ||
*/ | ||
fun startThread() { | ||
val iDriveConnectionStatus = IDriveConnectionReceiver() | ||
val securityAccess = SecurityAccess.getInstance(applicationContext) | ||
if (iDriveConnectionStatus.isConnected && | ||
securityAccess.isConnected() && | ||
thread?.isAlive != true) { | ||
|
||
L.loadResources(applicationContext) | ||
thread = CarThread("ScreenMirroring") { | ||
app = CarApp( | ||
iDriveConnectionStatus, | ||
securityAccess, | ||
CarAppAssetResources(applicationContext, "smartthings"), | ||
ScreenMirrorProvider(thread?.handler!!) | ||
) { | ||
// start up the notification when we enter the app | ||
val foreground = NotificationService.shouldBeForeground() | ||
NotificationService.startNotification(applicationContext, foreground) | ||
} | ||
} | ||
thread?.start() | ||
} | ||
} | ||
|
||
override fun onDestroy() { | ||
super.onDestroy() | ||
|
||
app?.onDestroy() | ||
NotificationService.stopNotification(applicationContext) | ||
} | ||
} |
Oops, something went wrong.