diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 65dc2790..87c4dc52 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,7 +16,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Validate Gradle Wrapper uses: gradle/wrapper-validation-action@v1 @@ -46,25 +46,25 @@ jobs: run: ./gradlew testDebug - name: Upload build outputs (APKs) - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: build-outputs path: app/build/outputs - name: Upload build reports if: always() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: build-reports path: app/build/reports androidTest: needs: build - runs-on: macOS-latest # enables hardware acceleration in the virtual machine + runs-on: macos-latest-large timeout-minutes: 55 strategy: matrix: - api-level: [26, 30] + api-level: [31, 34] steps: - name: Checkout @@ -94,7 +94,7 @@ jobs: - name: Upload test reports if: always() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: test-reports-${{ matrix.api-level }} path: '*/build/reports/androidTests' diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 4e383b1e..4e2fdeaa 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -34,7 +34,7 @@ android { defaultConfig { applicationId = "com.example.platform.app" - minSdk = 21 + minSdk = 24 targetSdk = 34 versionCode = 1 versionName = "1.0" diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f385dfb1..a4bad604 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -18,7 +18,7 @@ accompanist = "0.32.0" androidx-datastore = "1.0.0" androidx-navigation = "2.7.7" androidx-window = "1.2.0" -agp = "8.2.2" +agp = "8.4.1" casa = "0.5.1" coil = "2.4.0" ksp = "1.9.22-1.0.17" diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 3ce71f6b..364bf915 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -17,6 +17,6 @@ #Wed Dec 07 13:21:03 CET 2022 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/samples/README.md b/samples/README.md index 8a0606ec..7b9f3523 100644 --- a/samples/README.md +++ b/samples/README.md @@ -90,6 +90,8 @@ Shows Predictive Back animations. Add your custom tile to the Quick Settings. - [Receive data shared by other apps](user-interface/share/src/main/java/com/example/platform/ui/share/receiver/ShareReceiverActivity.kt): Receive texts and images from other apps. +- [SaferIntents](security/intents/src/main/java/com/example/platform/security/intents/SaferIntents.kt): +Example on how can fix the miss use of intents - [Scan with BLE Intent](connectivity/bluetooth/ble/src/main/java/com/example/platform/connectivity/bluetooth/ble/BLEScanIntentSample.kt): This samples shows how to use the BLE intent to scan for devices - [Screenshot Detection](privacy/transparency/src/main/java/com/example/platform/privacy/transparency/ScreenshotDetection.kt): diff --git a/samples/security/intents/README.md b/samples/security/intents/README.md new file mode 100644 index 00000000..dc5e9321 --- /dev/null +++ b/samples/security/intents/README.md @@ -0,0 +1,10 @@ +# SaferIntents samples + +This sample shows that it is important to not have a NULL intent. +It contains 2 buttons: + +- One button sends an NULL intent +- Another button sends a regular intent + +It is important to note that for the NULL intent an exception handling has taken place. +If an app sends a NULL intent it will crash with an `ActivityNotFound` exception \ No newline at end of file diff --git a/samples/security/intents/build.gradle.kts b/samples/security/intents/build.gradle.kts new file mode 100644 index 00000000..3fa741f0 --- /dev/null +++ b/samples/security/intents/build.gradle.kts @@ -0,0 +1,29 @@ + +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +plugins { + id("com.example.platform.sample") +} + +android { + namespace = "com.example.platform.security.intents" +} + +dependencies { + // Add samples specific dependencies +} \ No newline at end of file diff --git a/samples/security/intents/src/main/AndroidManifest.xml b/samples/security/intents/src/main/AndroidManifest.xml new file mode 100644 index 00000000..b490a4c1 --- /dev/null +++ b/samples/security/intents/src/main/AndroidManifest.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + diff --git a/samples/security/intents/src/main/java/com/example/platform/security/intents/SaferIntents.kt b/samples/security/intents/src/main/java/com/example/platform/security/intents/SaferIntents.kt new file mode 100644 index 00000000..fbdfce42 --- /dev/null +++ b/samples/security/intents/src/main/java/com/example/platform/security/intents/SaferIntents.kt @@ -0,0 +1,72 @@ + +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package com.example.platform.security.intents + +import android.annotation.SuppressLint +import android.content.ActivityNotFoundException +import android.content.Intent +import android.widget.Toast +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Button +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.unit.dp +import com.google.android.catalog.framework.annotations.Sample + +@Sample( + name = "SaferIntents", + description = "Example on how can fix the miss use of intents" +) +@SuppressLint("IntentWithNullActionLaunch") +@Composable +fun SaferIntents() { + val context = LocalContext.current + + Column ( + modifier = Modifier + .fillMaxSize() + .padding(16.dp), + verticalArrangement = Arrangement.spacedBy(8.dp), + horizontalAlignment = Alignment.CenterHorizontally, + ){ + Button(onClick = { + val intent = Intent() + try { + context.startActivity(intent) + } catch (e : ActivityNotFoundException) { + Toast.makeText(context, "Error: " + e.message, Toast.LENGTH_SHORT).show() + } + }) { + Text(text = "Send NULL Intent") + } + + Button(onClick = { + val intent = Intent("com.example.platform.security.intents.MY_ACTION") + context.startActivity(intent) + }) { + Text(text = "Send Intent") + } + } +} \ No newline at end of file diff --git a/samples/security/intents/src/main/java/com/example/platform/security/intents/SaferIntentsActivity.kt b/samples/security/intents/src/main/java/com/example/platform/security/intents/SaferIntentsActivity.kt new file mode 100644 index 00000000..a110cb0a --- /dev/null +++ b/samples/security/intents/src/main/java/com/example/platform/security/intents/SaferIntentsActivity.kt @@ -0,0 +1,56 @@ + +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.example.platform.security.intents + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.os.Bundle +import android.util.Log +import android.widget.Toast +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier + +class SaferIntentsActivity : ComponentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + Toast.makeText(applicationContext, "Activity successfully created", Toast.LENGTH_SHORT).show() + + setContent { + MaterialTheme { + Surface ( + Modifier + .fillMaxSize() + .background(MaterialTheme.colorScheme.background) + ){ + HelloAndroidScreen() + } + } + } + } +} +@Composable +fun HelloAndroidScreen() { + Text(text = "Hello Android!") +} \ No newline at end of file