[battery] Support the v2 Android embedder (#2152)


diff --git a/packages/battery/CHANGELOG.md b/packages/battery/CHANGELOG.md
index 5c90736..172550e 100644
--- a/packages/battery/CHANGELOG.md
+++ b/packages/battery/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.3.1
+
+* Support the v2 Android embedder.
+
 ## 0.3.0+6
 
 * Define clang module for iOS.
diff --git a/packages/battery/android/build.gradle b/packages/battery/android/build.gradle
index ed302d2..e4c2449 100644
--- a/packages/battery/android/build.gradle
+++ b/packages/battery/android/build.gradle
@@ -45,3 +45,28 @@
         disable 'InvalidPackage'
     }
 }
+
+// TODO(amirh): Remove this hack once androidx.lifecycle is included on stable. https://github.com/flutter/flutter/issues/42348
+afterEvaluate {
+    def containsEmbeddingDependencies = false
+    for (def configuration : configurations.all) {
+        for (def dependency : configuration.dependencies) {
+            if (dependency.group == 'io.flutter' &&
+                dependency.name.startsWith('flutter_embedding') &&
+                dependency.isTransitive())
+            {
+                containsEmbeddingDependencies = true
+                break
+            }
+        }
+    }
+    if (!containsEmbeddingDependencies) {
+        android {
+            dependencies {
+                def lifecycle_version = "2.1.0"
+                api "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
+                api "androidx.lifecycle:lifecycle-runtime:$lifecycle_version"
+            }
+        }
+    }
+}
diff --git a/packages/battery/android/src/main/java/io/flutter/plugins/battery/BatteryPlugin.java b/packages/battery/android/src/main/java/io/flutter/plugins/battery/BatteryPlugin.java
index b6d3e79..1bf3c24 100644
--- a/packages/battery/android/src/main/java/io/flutter/plugins/battery/BatteryPlugin.java
+++ b/packages/battery/android/src/main/java/io/flutter/plugins/battery/BatteryPlugin.java
@@ -12,6 +12,8 @@
 import android.os.BatteryManager;
 import android.os.Build.VERSION;
 import android.os.Build.VERSION_CODES;
+import io.flutter.embedding.engine.plugins.FlutterPlugin;
+import io.flutter.plugin.common.BinaryMessenger;
 import io.flutter.plugin.common.EventChannel;
 import io.flutter.plugin.common.EventChannel.EventSink;
 import io.flutter.plugin.common.EventChannel.StreamHandler;
@@ -22,25 +24,41 @@
 import io.flutter.plugin.common.PluginRegistry;
 
 /** BatteryPlugin */
-public class BatteryPlugin implements MethodCallHandler, StreamHandler {
+public class BatteryPlugin implements MethodCallHandler, StreamHandler, FlutterPlugin {
+
+  private Context applicationContext;
+  private BroadcastReceiver chargingStateChangeReceiver;
+  private MethodChannel methodChannel;
+  private EventChannel eventChannel;
 
   /** Plugin registration. */
   public static void registerWith(PluginRegistry.Registrar registrar) {
-    final MethodChannel methodChannel =
-        new MethodChannel(registrar.messenger(), "plugins.flutter.io/battery");
-    final EventChannel eventChannel =
-        new EventChannel(registrar.messenger(), "plugins.flutter.io/charging");
-    final BatteryPlugin instance = new BatteryPlugin(registrar);
-    eventChannel.setStreamHandler(instance);
-    methodChannel.setMethodCallHandler(instance);
+    final BatteryPlugin instance = new BatteryPlugin();
+    instance.onAttachedToEngine(registrar.context(), registrar.messenger());
   }
 
-  BatteryPlugin(PluginRegistry.Registrar registrar) {
-    this.registrar = registrar;
+  @Override
+  public void onAttachedToEngine(FlutterPluginBinding binding) {
+    onAttachedToEngine(
+        binding.getApplicationContext(), binding.getFlutterEngine().getDartExecutor());
   }
 
-  private final PluginRegistry.Registrar registrar;
-  private BroadcastReceiver chargingStateChangeReceiver;
+  private void onAttachedToEngine(Context applicationContext, BinaryMessenger messenger) {
+    this.applicationContext = applicationContext;
+    methodChannel = new MethodChannel(messenger, "plugins.flutter.io/battery");
+    eventChannel = new EventChannel(messenger, "plugins.flutter.io/charging");
+    eventChannel.setStreamHandler(this);
+    methodChannel.setMethodCallHandler(this);
+  }
+
+  @Override
+  public void onDetachedFromEngine(FlutterPluginBinding binding) {
+    applicationContext = null;
+    methodChannel.setMethodCallHandler(null);
+    methodChannel = null;
+    eventChannel.setStreamHandler(null);
+    eventChannel = null;
+  }
 
   @Override
   public void onMethodCall(MethodCall call, Result result) {
@@ -60,28 +78,25 @@
   @Override
   public void onListen(Object arguments, EventSink events) {
     chargingStateChangeReceiver = createChargingStateChangeReceiver(events);
-    registrar
-        .context()
-        .registerReceiver(
-            chargingStateChangeReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
+    applicationContext.registerReceiver(
+        chargingStateChangeReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
   }
 
   @Override
   public void onCancel(Object arguments) {
-    registrar.context().unregisterReceiver(chargingStateChangeReceiver);
+    applicationContext.unregisterReceiver(chargingStateChangeReceiver);
     chargingStateChangeReceiver = null;
   }
 
   private int getBatteryLevel() {
     int batteryLevel = -1;
-    Context context = registrar.context();
     if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
       BatteryManager batteryManager =
-          (BatteryManager) context.getSystemService(context.BATTERY_SERVICE);
+          (BatteryManager) applicationContext.getSystemService(applicationContext.BATTERY_SERVICE);
       batteryLevel = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY);
     } else {
       Intent intent =
-          new ContextWrapper(context)
+          new ContextWrapper(applicationContext)
               .registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
       batteryLevel =
           (intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) * 100)
diff --git a/packages/battery/example/android/app/src/androidTest/java/io/flutter/plugins/battery/EmbedderV1ActivityTest.java b/packages/battery/example/android/app/src/androidTest/java/io/flutter/plugins/battery/EmbedderV1ActivityTest.java
new file mode 100644
index 0000000..ef6e5d9
--- /dev/null
+++ b/packages/battery/example/android/app/src/androidTest/java/io/flutter/plugins/battery/EmbedderV1ActivityTest.java
@@ -0,0 +1,17 @@
+// Copyright 2019 The Chromium 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.batteryexample;
+
+import androidx.test.rule.ActivityTestRule;
+import dev.flutter.plugins.e2e.FlutterRunner;
+import org.junit.Rule;
+import org.junit.runner.RunWith;
+
+@RunWith(FlutterRunner.class)
+public class EmbedderV1ActivityTest {
+  @Rule
+  public ActivityTestRule<EmbedderV1Activity> rule =
+      new ActivityTestRule<>(EmbedderV1Activity.class);
+}
diff --git a/packages/battery/example/android/app/src/androidTest/java/io/flutter/plugins/battery/MainActivityTest.java b/packages/battery/example/android/app/src/androidTest/java/io/flutter/plugins/battery/MainActivityTest.java
new file mode 100644
index 0000000..16165ad
--- /dev/null
+++ b/packages/battery/example/android/app/src/androidTest/java/io/flutter/plugins/battery/MainActivityTest.java
@@ -0,0 +1,15 @@
+// Copyright 2019 The Chromium 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.batteryexample;
+
+import androidx.test.rule.ActivityTestRule;
+import dev.flutter.plugins.e2e.FlutterRunner;
+import org.junit.Rule;
+import org.junit.runner.RunWith;
+
+@RunWith(FlutterRunner.class)
+public class MainActivityTest {
+  @Rule public ActivityTestRule<MainActivity> rule = new ActivityTestRule<>(MainActivity.class);
+}
diff --git a/packages/battery/example/android/app/src/main/AndroidManifest.xml b/packages/battery/example/android/app/src/main/AndroidManifest.xml
index 6b07de4..e76af9c 100644
--- a/packages/battery/example/android/app/src/main/AndroidManifest.xml
+++ b/packages/battery/example/android/app/src/main/AndroidManifest.xml
@@ -15,5 +15,12 @@
                 <category android:name="android.intent.category.LAUNCHER"/>
             </intent-filter>
         </activity>
+        <activity
+            android:name=".EmbedderV1Activity"
+            android:theme="@android:style/Theme.Black.NoTitleBar"
+            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection"
+            android:hardwareAccelerated="true"
+            android:windowSoftInputMode="adjustResize">
+        </activity>
     </application>
 </manifest>
diff --git a/packages/battery/example/android/app/src/main/java/io/flutter/plugins/batteryexample/EmbedderV1Activity.java b/packages/battery/example/android/app/src/main/java/io/flutter/plugins/batteryexample/EmbedderV1Activity.java
new file mode 100644
index 0000000..f04a2e2
--- /dev/null
+++ b/packages/battery/example/android/app/src/main/java/io/flutter/plugins/batteryexample/EmbedderV1Activity.java
@@ -0,0 +1,17 @@
+// Copyright 2017 The Chromium 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.batteryexample;
+
+import android.os.Bundle;
+import io.flutter.app.FlutterActivity;
+import io.flutter.plugins.GeneratedPluginRegistrant;
+
+public class EmbedderV1Activity extends FlutterActivity {
+  @Override
+  protected void onCreate(Bundle savedInstanceState) {
+    super.onCreate(savedInstanceState);
+    GeneratedPluginRegistrant.registerWith(this);
+  }
+}
diff --git a/packages/battery/example/android/app/src/main/java/io/flutter/plugins/batteryexample/MainActivity.java b/packages/battery/example/android/app/src/main/java/io/flutter/plugins/batteryexample/MainActivity.java
index 320226f..26ae8ec 100644
--- a/packages/battery/example/android/app/src/main/java/io/flutter/plugins/batteryexample/MainActivity.java
+++ b/packages/battery/example/android/app/src/main/java/io/flutter/plugins/batteryexample/MainActivity.java
@@ -1,17 +1,16 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
+// Copyright 2019 The Chromium 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.batteryexample;
 
-import android.os.Bundle;
-import io.flutter.app.FlutterActivity;
-import io.flutter.plugins.GeneratedPluginRegistrant;
+import io.flutter.embedding.android.FlutterActivity;
+import io.flutter.embedding.engine.FlutterEngine;
+import io.flutter.plugins.battery.BatteryPlugin;
 
 public class MainActivity extends FlutterActivity {
   @Override
-  protected void onCreate(Bundle savedInstanceState) {
-    super.onCreate(savedInstanceState);
-    GeneratedPluginRegistrant.registerWith(this);
+  public void configureFlutterEngine(FlutterEngine flutterEngine) {
+    flutterEngine.getPlugins().add(new BatteryPlugin());
   }
 }
diff --git a/packages/battery/example/android/gradle.properties b/packages/battery/example/android/gradle.properties
index 8bd86f6..38c8d45 100644
--- a/packages/battery/example/android/gradle.properties
+++ b/packages/battery/example/android/gradle.properties
@@ -1 +1,4 @@
 org.gradle.jvmargs=-Xmx1536M
+android.enableR8=true
+android.useAndroidX=true
+android.enableJetifier=true
diff --git a/packages/battery/example/pubspec.yaml b/packages/battery/example/pubspec.yaml
index 1fde3d2..0c57142 100644
--- a/packages/battery/example/pubspec.yaml
+++ b/packages/battery/example/pubspec.yaml
@@ -7,5 +7,12 @@
   battery:
     path: ../
 
+dev_dependencies:
+  flutter_driver:
+    sdk: flutter
+
 flutter:
   uses-material-design: true
+
+environment:
+  flutter: ">=1.9.1+hotfix.4 <2.0.0"
diff --git a/packages/battery/pubspec.yaml b/packages/battery/pubspec.yaml
index c6a3f88..7314d27 100644
--- a/packages/battery/pubspec.yaml
+++ b/packages/battery/pubspec.yaml
@@ -3,7 +3,7 @@
   (full, charging, discharging) on Android and iOS.
 author: Flutter Team <flutter-dev@googlegroups.com>
 homepage: https://github.com/flutter/plugins/tree/master/packages/battery
-version: 0.3.0+6
+version: 0.3.1
 
 flutter:
   plugin:
@@ -22,7 +22,8 @@
   mockito: 3.0.0
   flutter_test:
     sdk: flutter
+  e2e: ^0.2.0
 
 environment:
   sdk: ">=2.0.0-dev.28.0 <3.0.0"
-  flutter: ">=1.2.0 <2.0.0"
+  flutter: ">=1.6.7 <2.0.0"
diff --git a/packages/battery/test/battery_e2e.dart b/packages/battery/test/battery_e2e.dart
new file mode 100644
index 0000000..6ffc7e6
--- /dev/null
+++ b/packages/battery/test/battery_e2e.dart
@@ -0,0 +1,17 @@
+// Copyright 2019, the Chromium project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:flutter_test/flutter_test.dart';
+import 'package:battery/battery.dart';
+import 'package:e2e/e2e.dart';
+
+void main() {
+  E2EWidgetsFlutterBinding.ensureInitialized();
+
+  testWidgets('Can get battery level', (WidgetTester tester) async {
+    final Battery battery = Battery();
+    final int batteryLevel = await battery.batteryLevel;
+    expect(batteryLevel, isNotNull);
+  });
+}