Enable Android integration tests in remaining plugins (#4514)

diff --git a/packages/camera/camera/CHANGELOG.md b/packages/camera/camera/CHANGELOG.md
index 929feea..1a6eceb 100644
--- a/packages/camera/camera/CHANGELOG.md
+++ b/packages/camera/camera/CHANGELOG.md
@@ -1,3 +1,8 @@
+##  0.9.4+5
+
+* Fixes bug where calling a method after the camera was closed resulted in a Java `IllegalStateException` exception.
+* Fixes integration tests.
+
 ## 0.9.4+4
 
 * Change Android compileSdkVersion to 31.
diff --git a/packages/camera/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java b/packages/camera/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java
index e319039..6a70ea0 100644
--- a/packages/camera/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java
+++ b/packages/camera/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java
@@ -281,8 +281,10 @@
           public void onClosed(@NonNull CameraDevice camera) {
             Log.i(TAG, "open | onClosed");
 
+            // Prevents calls to methods that would otherwise result in IllegalStateException exceptions.
+            cameraDevice = null;
+            closeCaptureSession();
             dartMessenger.sendCameraClosingEvent();
-            super.onClosed(camera);
           }
 
           @Override
@@ -364,10 +366,13 @@
     // Prepare the callback.
     CameraCaptureSession.StateCallback callback =
         new CameraCaptureSession.StateCallback() {
+          boolean captureSessionClosed = false;
+
           @Override
           public void onConfigured(@NonNull CameraCaptureSession session) {
+            Log.i(TAG, "CameraCaptureSession onConfigured");
             // Camera was already closed.
-            if (cameraDevice == null) {
+            if (cameraDevice == null || captureSessionClosed) {
               dartMessenger.sendCameraErrorEvent("The camera was closed during configuration.");
               return;
             }
@@ -382,8 +387,15 @@
 
           @Override
           public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
+            Log.i(TAG, "CameraCaptureSession onConfigureFailed");
             dartMessenger.sendCameraErrorEvent("Failed to configure camera session.");
           }
+
+          @Override
+          public void onClosed(@NonNull CameraCaptureSession session) {
+            Log.i(TAG, "CameraCaptureSession onClosed");
+            captureSessionClosed = true;
+          }
         };
 
     // Start the session.
@@ -427,10 +439,12 @@
   // Send a repeating request to refresh  capture session.
   private void refreshPreviewCaptureSession(
       @Nullable Runnable onSuccessCallback, @NonNull ErrorCallback onErrorCallback) {
+    Log.i(TAG, "refreshPreviewCaptureSession");
+
     if (captureSession == null) {
       Log.i(
           TAG,
-          "[refreshPreviewCaptureSession] captureSession not yet initialized, "
+          "refreshPreviewCaptureSession: captureSession not yet initialized, "
               + "skipping preview capture session refresh.");
       return;
     }
@@ -445,6 +459,8 @@
         onSuccessCallback.run();
       }
 
+    } catch (IllegalStateException e) {
+      onErrorCallback.onError("cameraAccess", "Camera is closed: " + e.getMessage());
     } catch (CameraAccessException e) {
       onErrorCallback.onError("cameraAccess", e.getMessage());
     }
diff --git a/packages/camera/camera/example/android/app/src/androidTestDebug/java/io/flutter/plugins/DartIntegrationTest.java b/packages/camera/camera/example/android/app/src/androidTest/java/io/flutter/plugins/DartIntegrationTest.java
similarity index 100%
rename from packages/camera/camera/example/android/app/src/androidTestDebug/java/io/flutter/plugins/DartIntegrationTest.java
rename to packages/camera/camera/example/android/app/src/androidTest/java/io/flutter/plugins/DartIntegrationTest.java
diff --git a/packages/camera/camera/example/android/app/src/androidTestDebug/java/io/flutter/plugins/cameraexample/FlutterActivityTest.java b/packages/camera/camera/example/android/app/src/androidTest/java/io/flutter/plugins/cameraexample/FlutterActivityTest.java
similarity index 100%
rename from packages/camera/camera/example/android/app/src/androidTestDebug/java/io/flutter/plugins/cameraexample/FlutterActivityTest.java
rename to packages/camera/camera/example/android/app/src/androidTest/java/io/flutter/plugins/cameraexample/FlutterActivityTest.java
diff --git a/packages/camera/camera/example/integration_test/camera_test.dart b/packages/camera/camera/example/integration_test/camera_test.dart
index 00a1714..d09300a 100644
--- a/packages/camera/camera/example/integration_test/camera_test.dart
+++ b/packages/camera/camera/example/integration_test/camera_test.dart
@@ -71,28 +71,32 @@
         expectedSize, Size(image.height.toDouble(), image.width.toDouble()));
   }
 
-  testWidgets('Capture specific image resolutions',
-      (WidgetTester tester) async {
-    final List<CameraDescription> cameras = await availableCameras();
-    if (cameras.isEmpty) {
-      return;
-    }
-    for (CameraDescription cameraDescription in cameras) {
-      bool previousPresetExactlySupported = true;
-      for (MapEntry<ResolutionPreset, Size> preset
-          in presetExpectedSizes.entries) {
-        final CameraController controller =
-            CameraController(cameraDescription, preset.key);
-        await controller.initialize();
-        final bool presetExactlySupported =
-            await testCaptureImageResolution(controller, preset.key);
-        assert(!(!previousPresetExactlySupported && presetExactlySupported),
-            'The camera took higher resolution pictures at a lower resolution.');
-        previousPresetExactlySupported = presetExactlySupported;
-        await controller.dispose();
+  testWidgets(
+    'Capture specific image resolutions',
+    (WidgetTester tester) async {
+      final List<CameraDescription> cameras = await availableCameras();
+      if (cameras.isEmpty) {
+        return;
       }
-    }
-  }, skip: !Platform.isAndroid);
+      for (CameraDescription cameraDescription in cameras) {
+        bool previousPresetExactlySupported = true;
+        for (MapEntry<ResolutionPreset, Size> preset
+            in presetExpectedSizes.entries) {
+          final CameraController controller =
+              CameraController(cameraDescription, preset.key);
+          await controller.initialize();
+          final bool presetExactlySupported =
+              await testCaptureImageResolution(controller, preset.key);
+          assert(!(!previousPresetExactlySupported && presetExactlySupported),
+              'The camera took higher resolution pictures at a lower resolution.');
+          previousPresetExactlySupported = presetExactlySupported;
+          await controller.dispose();
+        }
+      }
+    },
+    // TODO(egarciad): Fix https://github.com/flutter/flutter/issues/93686.
+    skip: true,
+  );
 
   // This tests that the capture is no bigger than the preset, since we have
   // automatic code to fall back to smaller sizes when we need to. Returns
@@ -121,29 +125,33 @@
         expectedSize, Size(video.height, video.width));
   }
 
-  testWidgets('Capture specific video resolutions',
-      (WidgetTester tester) async {
-    final List<CameraDescription> cameras = await availableCameras();
-    if (cameras.isEmpty) {
-      return;
-    }
-    for (CameraDescription cameraDescription in cameras) {
-      bool previousPresetExactlySupported = true;
-      for (MapEntry<ResolutionPreset, Size> preset
-          in presetExpectedSizes.entries) {
-        final CameraController controller =
-            CameraController(cameraDescription, preset.key);
-        await controller.initialize();
-        await controller.prepareForVideoRecording();
-        final bool presetExactlySupported =
-            await testCaptureVideoResolution(controller, preset.key);
-        assert(!(!previousPresetExactlySupported && presetExactlySupported),
-            'The camera took higher resolution pictures at a lower resolution.');
-        previousPresetExactlySupported = presetExactlySupported;
-        await controller.dispose();
+  testWidgets(
+    'Capture specific video resolutions',
+    (WidgetTester tester) async {
+      final List<CameraDescription> cameras = await availableCameras();
+      if (cameras.isEmpty) {
+        return;
       }
-    }
-  }, skip: !Platform.isAndroid);
+      for (CameraDescription cameraDescription in cameras) {
+        bool previousPresetExactlySupported = true;
+        for (MapEntry<ResolutionPreset, Size> preset
+            in presetExpectedSizes.entries) {
+          final CameraController controller =
+              CameraController(cameraDescription, preset.key);
+          await controller.initialize();
+          await controller.prepareForVideoRecording();
+          final bool presetExactlySupported =
+              await testCaptureVideoResolution(controller, preset.key);
+          assert(!(!previousPresetExactlySupported && presetExactlySupported),
+              'The camera took higher resolution pictures at a lower resolution.');
+          previousPresetExactlySupported = presetExactlySupported;
+          await controller.dispose();
+        }
+      }
+    },
+    // TODO(egarciad): Fix https://github.com/flutter/flutter/issues/93686.
+    skip: true,
+  );
 
   testWidgets('Pause and resume video recording', (WidgetTester tester) async {
     final List<CameraDescription> cameras = await availableCameras();
diff --git a/packages/camera/camera/pubspec.yaml b/packages/camera/camera/pubspec.yaml
index 905ec43..58e1ca3 100644
--- a/packages/camera/camera/pubspec.yaml
+++ b/packages/camera/camera/pubspec.yaml
@@ -4,7 +4,7 @@
   Dart.
 repository: https://github.com/flutter/plugins/tree/master/packages/camera/camera
 issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22
-version: 0.9.4+4
+version: 0.9.4+5
 
 environment:
   sdk: ">=2.14.0 <3.0.0"
diff --git a/packages/in_app_purchase/in_app_purchase/CHANGELOG.md b/packages/in_app_purchase/in_app_purchase/CHANGELOG.md
index 6b615fe..39d8ce8 100644
--- a/packages/in_app_purchase/in_app_purchase/CHANGELOG.md
+++ b/packages/in_app_purchase/in_app_purchase/CHANGELOG.md
@@ -1,5 +1,6 @@
 ## NEXT
 
+* Fixes integration tests.
 * Updates example app Android compileSdkVersion to 31.
 
 * **BREAKING CHANGES**:
diff --git a/packages/in_app_purchase/in_app_purchase/example/android/app/src/main/java/io/flutter/plugins/DartIntegrationTest.java b/packages/in_app_purchase/in_app_purchase/example/android/app/src/androidTest/java/io/flutter/plugins/DartIntegrationTest.java
similarity index 100%
rename from packages/in_app_purchase/in_app_purchase/example/android/app/src/main/java/io/flutter/plugins/DartIntegrationTest.java
rename to packages/in_app_purchase/in_app_purchase/example/android/app/src/androidTest/java/io/flutter/plugins/DartIntegrationTest.java
diff --git a/packages/in_app_purchase/in_app_purchase/example/android/app/src/main/java/io/flutter/plugins/inapppurchaseexample/FlutterActivityTest.java b/packages/in_app_purchase/in_app_purchase/example/android/app/src/androidTest/java/io/flutter/plugins/inapppurchaseexample/FlutterActivityTest.java
similarity index 100%
rename from packages/in_app_purchase/in_app_purchase/example/android/app/src/main/java/io/flutter/plugins/inapppurchaseexample/FlutterActivityTest.java
rename to packages/in_app_purchase/in_app_purchase/example/android/app/src/androidTest/java/io/flutter/plugins/inapppurchaseexample/FlutterActivityTest.java
diff --git a/packages/in_app_purchase/in_app_purchase/example/android/app/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/packages/in_app_purchase/in_app_purchase/example/android/app/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
deleted file mode 100644
index 1f0955d..0000000
--- a/packages/in_app_purchase/in_app_purchase/example/android/app/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
+++ /dev/null
@@ -1 +0,0 @@
-mock-maker-inline
diff --git a/packages/in_app_purchase/in_app_purchase/example/integration_test/in_app_purchase_test.dart b/packages/in_app_purchase/in_app_purchase/example/integration_test/in_app_purchase_test.dart
index 437ee99..55ad122 100644
--- a/packages/in_app_purchase/in_app_purchase/example/integration_test/in_app_purchase_test.dart
+++ b/packages/in_app_purchase/in_app_purchase/example/integration_test/in_app_purchase_test.dart
@@ -2,14 +2,21 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import 'dart:io';
+
 import 'package:flutter_test/flutter_test.dart';
 import 'package:in_app_purchase/in_app_purchase.dart';
+import 'package:in_app_purchase_android/in_app_purchase_android.dart';
 import 'package:integration_test/integration_test.dart';
 
 void main() {
   IntegrationTestWidgetsFlutterBinding.ensureInitialized();
 
   testWidgets('Can create InAppPurchase instance', (WidgetTester tester) async {
+    if (Platform.isAndroid) {
+      // https://github.com/flutter/flutter/issues/93837
+      InAppPurchaseAndroidPlatformAddition.enablePendingPurchases();
+    }
     final InAppPurchase iapInstance = InAppPurchase.instance;
     expect(iapInstance, isNotNull);
   });
diff --git a/packages/in_app_purchase/in_app_purchase_android/example/android/app/src/main/java/io/flutter/plugins/DartIntegrationTest.java b/packages/in_app_purchase/in_app_purchase_android/example/android/app/src/androidTest/java/io/flutter/plugins/DartIntegrationTest.java
similarity index 100%
rename from packages/in_app_purchase/in_app_purchase_android/example/android/app/src/main/java/io/flutter/plugins/DartIntegrationTest.java
rename to packages/in_app_purchase/in_app_purchase_android/example/android/app/src/androidTest/java/io/flutter/plugins/DartIntegrationTest.java
diff --git a/packages/in_app_purchase/in_app_purchase_android/example/android/app/src/main/java/io/flutter/plugins/inapppurchaseexample/FlutterActivityTest.java b/packages/in_app_purchase/in_app_purchase_android/example/android/app/src/androidTest/java/io/flutter/plugins/inapppurchaseexample/FlutterActivityTest.java
similarity index 100%
rename from packages/in_app_purchase/in_app_purchase_android/example/android/app/src/main/java/io/flutter/plugins/inapppurchaseexample/FlutterActivityTest.java
rename to packages/in_app_purchase/in_app_purchase_android/example/android/app/src/androidTest/java/io/flutter/plugins/inapppurchaseexample/FlutterActivityTest.java
diff --git a/packages/shared_preferences/shared_preferences/example/android/app/src/androidTest/java/io/flutter/plugins/sharedpreferencesexample/FlutterActivityTest.java b/packages/shared_preferences/shared_preferences/example/android/app/src/androidTest/java/io/flutter/plugins/sharedpreferencesexample/FlutterActivityTest.java
new file mode 100644
index 0000000..3d4ea2b
--- /dev/null
+++ b/packages/shared_preferences/shared_preferences/example/android/app/src/androidTest/java/io/flutter/plugins/sharedpreferencesexample/FlutterActivityTest.java
@@ -0,0 +1,19 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package io.flutter.plugins.sharedpreferencesexample;
+
+import androidx.test.rule.ActivityTestRule;
+import dev.flutter.plugins.integration_test.FlutterTestRunner;
+import io.flutter.embedding.android.FlutterActivity;
+import io.flutter.plugins.DartIntegrationTest;
+import org.junit.Rule;
+import org.junit.runner.RunWith;
+
+@DartIntegrationTest
+@RunWith(FlutterTestRunner.class)
+public class FlutterActivityTest {
+  @Rule
+  public ActivityTestRule<FlutterActivity> rule = new ActivityTestRule<>(FlutterActivity.class);
+}
diff --git a/packages/shared_preferences/shared_preferences/example/android/app/src/debug/AndroidManifest.xml b/packages/shared_preferences/shared_preferences/example/android/app/src/debug/AndroidManifest.xml
deleted file mode 100644
index d60d6f6..0000000
--- a/packages/shared_preferences/shared_preferences/example/android/app/src/debug/AndroidManifest.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="io.flutter.plugins.sharedpreferencesexample">
-    <!-- Flutter needs it to communicate with the running application
-         to allow setting breakpoints, to provide hot reload, etc.
-    -->
-    <uses-permission android:name="android.permission.INTERNET"/>
-</manifest>
diff --git a/packages/shared_preferences/shared_preferences/example/android/build.gradle b/packages/shared_preferences/shared_preferences/example/android/build.gradle
index 24047dc..21d5069 100644
--- a/packages/shared_preferences/shared_preferences/example/android/build.gradle
+++ b/packages/shared_preferences/shared_preferences/example/android/build.gradle
@@ -6,7 +6,7 @@
     }
 
     dependencies {
-        classpath 'com.android.tools.build:gradle:4.1.0'
+        classpath 'com.android.tools.build:gradle:7.0.1'
         classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
     }
 }
diff --git a/packages/shared_preferences/shared_preferences/example/android/gradle/wrapper/gradle-wrapper.properties b/packages/shared_preferences/shared_preferences/example/android/gradle/wrapper/gradle-wrapper.properties
index bc6a58a..b8793d3 100644
--- a/packages/shared_preferences/shared_preferences/example/android/gradle/wrapper/gradle-wrapper.properties
+++ b/packages/shared_preferences/shared_preferences/example/android/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip
diff --git a/packages/url_launcher/url_launcher/CHANGELOG.md b/packages/url_launcher/url_launcher/CHANGELOG.md
index aaa4d4e..e69083d 100644
--- a/packages/url_launcher/url_launcher/CHANGELOG.md
+++ b/packages/url_launcher/url_launcher/CHANGELOG.md
@@ -1,5 +1,7 @@
-## NEXT
+## 6.0.14
 
+* Updates readme to indicate that sending SMS messages on Android 11 requires to add a query to AndroidManifest.xml.
+* Fixes integration tests.
 * Updates example app Android compileSdkVersion to 31.
 
 ## 6.0.13
diff --git a/packages/url_launcher/url_launcher/README.md b/packages/url_launcher/url_launcher/README.md
index c649b5c..aa16132 100644
--- a/packages/url_launcher/url_launcher/README.md
+++ b/packages/url_launcher/url_launcher/README.md
@@ -72,7 +72,12 @@
     <action android:name="android.intent.action.DIAL" />
     <data android:scheme="tel" />
   </intent>
-  <!-- If your app emails -->
+  <!-- If your sends SMS messages -->
+  <intent>
+    <action android:name="android.intent.action.SENDTO" />
+    <data android:scheme="smsto" />
+  </intent>
+  <!-- If your app sends emails -->
   <intent>
     <action android:name="android.intent.action.SEND" />
     <data android:mimeType="*/*" />
diff --git a/packages/url_launcher/url_launcher/android/src/main/java/io/flutter/plugins/urllauncher/UrlLauncher.java b/packages/url_launcher/url_launcher/android/src/main/java/io/flutter/plugins/urllauncher/UrlLauncher.java
index 07f7ef3..c3a563a 100644
--- a/packages/url_launcher/url_launcher/android/src/main/java/io/flutter/plugins/urllauncher/UrlLauncher.java
+++ b/packages/url_launcher/url_launcher/android/src/main/java/io/flutter/plugins/urllauncher/UrlLauncher.java
@@ -12,11 +12,14 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.provider.Browser;
+import android.util.Log;
 import androidx.annotation.Nullable;
 
 /** Launches components for URLs. */
 class UrlLauncher {
+  private static final String TAG = "UrlLauncher";
   private final Context applicationContext;
+
   @Nullable private Activity activity;
 
   /**
@@ -40,9 +43,14 @@
     ComponentName componentName =
         launchIntent.resolveActivity(applicationContext.getPackageManager());
 
-    return componentName != null
-        && !"{com.android.fallback/com.android.fallback.Fallback}"
-            .equals(componentName.toShortString());
+    if (componentName == null) {
+      Log.i(TAG, "component name for " + url + " is null");
+      return false;
+    } else {
+      Log.i(TAG, "component name for " + url + " is " + componentName.toShortString());
+      return !"{com.android.fallback/com.android.fallback.Fallback}"
+          .equals(componentName.toShortString());
+    }
   }
 
   /**
diff --git a/packages/url_launcher/url_launcher/example/android/app/src/androidTestDebug/java/io/flutter/plugins/DartIntegrationTest.java b/packages/url_launcher/url_launcher/example/android/app/src/androidTest/java/io/flutter/plugins/DartIntegrationTest.java
similarity index 100%
rename from packages/url_launcher/url_launcher/example/android/app/src/androidTestDebug/java/io/flutter/plugins/DartIntegrationTest.java
rename to packages/url_launcher/url_launcher/example/android/app/src/androidTest/java/io/flutter/plugins/DartIntegrationTest.java
diff --git a/packages/url_launcher/url_launcher/example/android/app/src/androidTestDebug/java/io/flutter/plugins/urllauncherexample/MainActivityTest.java b/packages/url_launcher/url_launcher/example/android/app/src/androidTest/java/io/flutter/plugins/urllauncherexample/FlutterActivityTest.java
similarity index 100%
rename from packages/url_launcher/url_launcher/example/android/app/src/androidTestDebug/java/io/flutter/plugins/urllauncherexample/MainActivityTest.java
rename to packages/url_launcher/url_launcher/example/android/app/src/androidTest/java/io/flutter/plugins/urllauncherexample/FlutterActivityTest.java
diff --git a/packages/url_launcher/url_launcher/example/android/app/src/main/AndroidManifest.xml b/packages/url_launcher/url_launcher/example/android/app/src/main/AndroidManifest.xml
index 918c29e..fa149f9 100644
--- a/packages/url_launcher/url_launcher/example/android/app/src/main/AndroidManifest.xml
+++ b/packages/url_launcher/url_launcher/example/android/app/src/main/AndroidManifest.xml
@@ -17,6 +17,10 @@
       <action android:name="android.intent.action.DIAL" />
       <data android:scheme="tel" />
     </intent>
+    <intent>
+      <action android:name="android.intent.action.SENDTO" />
+      <data android:scheme="smsto" />
+    </intent>
   </queries>
 
   <application
diff --git a/packages/url_launcher/url_launcher/example/integration_test/url_launcher_test.dart b/packages/url_launcher/url_launcher/example/integration_test/url_launcher_test.dart
index 1413699..b527c22 100644
--- a/packages/url_launcher/url_launcher/example/integration_test/url_launcher_test.dart
+++ b/packages/url_launcher/url_launcher/example/integration_test/url_launcher_test.dart
@@ -17,6 +17,7 @@
 
     // Generally all devices should have some default browser.
     expect(await canLaunch('http://flutter.dev'), true);
+    expect(await canLaunch('https://www.google.com/404'), true);
 
     // SMS handling is available by default on most platforms.
     if (kIsWeb || !(Platform.isLinux || Platform.isWindows)) {
diff --git a/packages/url_launcher/url_launcher/pubspec.yaml b/packages/url_launcher/url_launcher/pubspec.yaml
index e057115..3296714 100644
--- a/packages/url_launcher/url_launcher/pubspec.yaml
+++ b/packages/url_launcher/url_launcher/pubspec.yaml
@@ -3,7 +3,7 @@
   web, phone, SMS, and email schemes.
 repository: https://github.com/flutter/plugins/tree/master/packages/url_launcher/url_launcher
 issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+url_launcher%22
-version: 6.0.13
+version: 6.0.14
 
 environment:
   sdk: ">=2.14.0 <3.0.0"
diff --git a/packages/video_player/video_player/CHANGELOG.md b/packages/video_player/video_player/CHANGELOG.md
index d6b50d1..7e9dfff 100644
--- a/packages/video_player/video_player/CHANGELOG.md
+++ b/packages/video_player/video_player/CHANGELOG.md
@@ -1,5 +1,6 @@
 ## NEXT
 
+* Fixes integration tests.
 * Updates example app Android compileSdkVersion to 31.
 
 ## 2.2.7
diff --git a/packages/camera/camera/example/android/app/src/androidTestDebug/java/io/flutter/plugins/DartIntegrationTest.java b/packages/video_player/video_player/example/android/app/src/androidTest/java/io/flutter/plugins/DartIntegrationTest.java
similarity index 100%
copy from packages/camera/camera/example/android/app/src/androidTestDebug/java/io/flutter/plugins/DartIntegrationTest.java
copy to packages/video_player/video_player/example/android/app/src/androidTest/java/io/flutter/plugins/DartIntegrationTest.java
diff --git a/packages/video_player/video_player/example/android/app/src/androidTest/java/io/flutter/plugins/videoplayerexample/FlutterActivityTest.java b/packages/video_player/video_player/example/android/app/src/androidTest/java/io/flutter/plugins/videoplayerexample/FlutterActivityTest.java
new file mode 100644
index 0000000..45cf5c6
--- /dev/null
+++ b/packages/video_player/video_player/example/android/app/src/androidTest/java/io/flutter/plugins/videoplayerexample/FlutterActivityTest.java
@@ -0,0 +1,19 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package io.flutter.plugins.videoplayerexample;
+
+import androidx.test.rule.ActivityTestRule;
+import dev.flutter.plugins.integration_test.FlutterTestRunner;
+import io.flutter.embedding.android.FlutterActivity;
+import io.flutter.plugins.DartIntegrationTest;
+import org.junit.Rule;
+import org.junit.runner.RunWith;
+
+@DartIntegrationTest
+@RunWith(FlutterTestRunner.class)
+public class FlutterActivityTest {
+  @Rule
+  public ActivityTestRule<FlutterActivity> rule = new ActivityTestRule<>(FlutterActivity.class);
+}
diff --git a/script/configs/exclude_integration_android.yaml b/script/configs/exclude_integration_android.yaml
index e6ef826..e06b062 100644
--- a/script/configs/exclude_integration_android.yaml
+++ b/script/configs/exclude_integration_android.yaml
@@ -1,10 +1,3 @@
-# Currently missing harness files: https://github.com/flutter/flutter/issues/86749
-- camera/camera
-- in_app_purchase/in_app_purchase
-- in_app_purchase_android
-- url_launcher/url_launcher
-- video_player/video_player
-
 # Deprecated; no plan to backfill the missing files
 - android_intent
 - connectivity/connectivity