Flutter应用程序-关闭屏幕的能力

3

有没有办法在 Flutter 应用程序中锁定 Android 屏幕? 我说的是当用户按下手机电源按钮时发生的相同操作。

2个回答

4

目前Flutter还不支持此功能,因此我们需要借助原生实现。请按照以下实现步骤。

Flutter代码:

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  static const platform = const MethodChannel('flutter.native/powerOff');

  Future<void> responseFromNativeCode() async {
    try {
      await platform.invokeMethod('powerOff');
    } on PlatformException catch (e) {
      print("Failed to Invoke: '${e.message}'.");
    }
  }

  @override
  Widget build(BuildContext context) {
    return Material(
      child: Center(
        child: RaisedButton(
          child: Text('Turn Off'),
          onPressed: responseFromNativeCode,
        ),
      ),
    );
  }
}

Java代码:

1. MainActivity

    import io.flutter.embedding.android.FlutterActivity;
    import io.flutter.embedding.engine.FlutterEngine;
    import io.flutter.plugin.common.MethodCall;
    import io.flutter.plugin.common.MethodChannel;
    import android.content.Context;
    import android.app.Activity;
    import android.app.admin.DevicePolicyManager;
    import android.content.ComponentName;
    import android.content.Intent;
    import android.content.IntentFilter;
    import android.widget.Toast;

    public class MainActivity extends FlutterActivity {
        private static final String CHANNEL = "flutter.native/powerOff";
        static final int RESULT_ENABLE = 1;
        DevicePolicyManager deviceManger;
        ComponentName compName;

    @Override
    public void configureFlutterEngine(FlutterEngine flutterEngine) {
        compName = new ComponentName(this, DeviceAdmin.class);
        deviceManger = (DevicePolicyManager)
                getSystemService(Context.DEVICE_POLICY_SERVICE);
        super.configureFlutterEngine(flutterEngine);
        new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL).setMethodCallHandler(
                new MethodChannel.MethodCallHandler() {
                    @Override
                    public void onMethodCall(MethodCall call, MethodChannel.Result result) {
                        if (call.method.equals("powerOff")) {
                            Intent intent = new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
                            intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, compName);
                            intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, "You should enable the app!");
                            startActivityForResult(intent, RESULT_ENABLE);
                        }
                    }
                });
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
            case RESULT_ENABLE:
                if (resultCode == Activity.RESULT_OK) {
                    deviceManger.lockNow();
                }
                return;
        }
    }
}

2. 接收方代码

import android.app.admin.DeviceAdminReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;

public class DeviceAdmin extends DeviceAdminReceiver {
    @Override
    public void onEnabled(Context context, Intent intent) {
        super.onEnabled(context, intent);
        Toast.makeText(context, "Enabled", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onDisabled(Context context, Intent intent) {
        super.onDisabled(context, intent);
        Toast.makeText(context, "Disabled", Toast.LENGTH_SHORT).show();
    }
}

3. AndroidMenifest.xml

 <receiver
        android:name=".DeviceAdmin"
        android:description="@string/app_description"
        android:label="@string/app_name"
        android:permission="android.permission.BIND_DEVICE_ADMIN">
        <meta-data
            android:name="android.app.device_admin"
            android:resource="@xml/policies" />
        <intent-filter>
            <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
        </intent-filter>
    </receiver>

4.policies.xml - 放入res/xml文件夹中

<?xml version="1.0" encoding="utf-8"?>
<device-admin>
    <uses-policies>
        <force-lock />
    </uses-policies>
</device-admin>

最后,在 Android 项目的 strings.xml 文件中添加字符串值,该字符串值在接收器中被要求使用。

谢谢您的回复!我还没有尝试过,因为我无法在我的项目中找到所有这些文件。我想我需要先在Android Studio中创建一个Android项目。 - emvaized
也许你的解决方案可以作为某种插件实现,所以唯一需要做的就是简单地导入它?这样做难吗? - emvaized

3

你好,也许我的回答有点晚,但我制作了一个插件,完全实现了下面评论中提到的功能,并附带了一些其他函数。

device_policy_manager

以下是如何使用它:

/// Return `true` if the given administrator component is currently active (enabled) in the system.
final status = await DevicePolicyManager.isPermissionGranted();

/// request administrator permission
/// it will open the adminstartor permission page and return `true` once the permission granted.
/// An optional message providing additional explanation for why the admin is being added.
await DevicePolicyManager.requestPermession("Your app is requesting the Adminstration permission");

/// Remove administration permission from the current app.
await DevicePolicyManager.removeActiveAdmin();

/// Make the device lock immediately, as if the lock screen timeout has expired at the point of this call.
/// After this method is called, the device must be unlocked using strong authentication (PIN, pattern, or password).
await DevicePolicyManager.lockNow();

/// Determine whether or not the device's cameras have been disabled for this user.
final status = await DevicePolicyManager.isCameraDisabled();

尝试后,我发现在锁定屏幕后,它会阻止用户使用指纹或面部数据打开手机,如何防止这种行为,只能使用锁定图案解锁。 - Ali Nour
根据文档所述,该方法会立即锁定设备,就好像在调用此方法时锁屏超时已经到期一样。调用此方法后,必须使用强身份验证(PIN、图案或密码)解锁设备。文档 - Iheb Briki

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接