Is there any way to lock the screen from Flutter app on Android?
I'm talking about the same action that happens when the user presses the phone's power button.
This is not available on flutter till now, for it we have to take the help of native implementation. Follow the below implementation.
Flutter Code:
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 Code:
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. Receiver Code
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 - Add in res/xml folder
<?xml version="1.0" encoding="utf-8"?>
<device-admin>
<uses-policies>
<force-lock />
</uses-policies>
</device-admin>
and Finally, add String value in strings.xml file of the android project which required in the receiver
Hello maybe my answer is late but I made a plugin that performs exactly the implementation mentioned in the comment below with some other functions
device_policy_manager
and this how u can use it
/// 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();
Related
I'm trying to implement google ads through admob_flutter package, created adunitId through admob account. but these adUnitId are not showing ads.
when I'm using ca-app-pub-3940256099942544/2934735716 this adUnitId then it is showing test ads on google ad.
Here is my code:
import 'dart:async';
import 'dart:io';
import 'package:admob_flutter/admob_flutter.dart';
import 'package:flutter/material.dart';
class GoogleAdBanner extends StatefulWidget {
GoogleAdBanner(this.size);
final AdmobBannerSize size;
#override
State<StatefulWidget> createState() => BannerAdState();
}
class BannerAdState extends State<GoogleAdBanner> {
AdmobBanner _bannerAd;
final Completer<AdmobBanner> bannerCompleter = Completer<AdmobBanner>();
#override
void initState() {
super.initState();
Admob.requestTrackingAuthorization();
}
String getBannerAdUnitId() {
if (Platform.isIOS) {
return 'ca-app-pub-7282911616152886/6377817226';
} else if (Platform.isAndroid) {
return 'ca-app-pub-7282911616152886/8046122111';
}
return null;
}
void handleEvent(
AdmobAdEvent event, Map<String, dynamic> args, String adType) {
switch (event) {
case AdmobAdEvent.loaded:
print('New Admob $adType Ad loaded!');
break;
case AdmobAdEvent.opened:
print('Admob $adType Ad opened!');
break;
case AdmobAdEvent.closed:
print('Admob $adType Ad closed!');
break;
case AdmobAdEvent.failedToLoad:
print('Admob $adType failed to load. :(');
break;
default:
}
}
#override
Widget build(BuildContext context) {
return AdmobBanner(
adUnitId: getBannerAdUnitId(), //'ca-app-pub-3940256099942544/2934735716',
adSize: widget.size,
listener: (AdmobAdEvent event,
Map<String, dynamic> args) {
handleEvent(event, args, 'Banner');
},
onBannerCreated: (AdmobBannerController controller) {},
);
}
}
using it as
GoogleAdBanner(AdmobBannerSize.LARGE_BANNER)
Please help with this. Thanks in advance!
Real ads are displayed only when there are enough number of requests. The inventory is empty till the threshold has reached. If you are able to see the test ads you can be assured that the implementation is right. Make sure you change the ad app id in manifest and info.plist and add the right ad unit ad in ad request before release.
use getBannerAdUnitId() like this:-
String get BannerAdUnitId(){
//body
}
adUnitId: BannerAdUnitId(),
i´m trying to get the link of the video of this page with the package "web_scraper". I can find it using Chrome´s tools (is an attribute of a jw-video jw-reset element. The problem is that when you enter the page you can´t see this attribute before clicking in the play button. Can any one help me?
I have already this code:
import 'package:flutter/material.dart';
import 'package:web_scraper/web_scraper.dart';
class Prueba extends StatefulWidget {
#override
State createState() => new _Prueba();
}
class _Prueba extends State<Prueba> {
final webScraper = WebScraper('https://www3.animeflv.net');
List<Map<String, dynamic>> link;
void fetchProducts() async {
// Loads web page and downloads into local state of library
if (await webScraper
.loadWebPage('/ver/sword-art-online-alicization-war-of-underworld-20')) {
setState(() {
link = webScraper.getElement(
'div.jw-wrapper.jw-reset > div.jw-media.jw-reset > video.jw-video.jw-reset', ['src']);
});
}
}
#override
void initState() {
super.initState();
// Requesting to fetch before UI drawing starts
fetchProducts();
}
#override
Widget build (BuildContext ctxt) {
print(link);
return Container();
}
}
Problem
I'm using riverpod and state_notifier.
The initState() and update() that StateNotifier has are called and No. The other member functions can be called successfully. However, other member functions can be called successfully.
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:riverpod_todo_list/todo_list_notifier.dart';
import 'package:riverpod_todo_list/todo_list_state.dart';
void main() {
print('start~~');
runApp(ProviderScope(child: MyApp()));
}
class MyApp extends HookWidget {
// ...
}
final todoListProvider = StateNotifierProvider((_) => TodoListNotifier());
class MyHomePage extends HookWidget {
final _controller = TextEditingController();
final todoListNotifier = useProvider(todoListProvider);
final TodoListState _todoListState =
useProvider(todoListProvider.state.select((value) => value));
//...
import 'package:riverpod_todo_list/todo.dart';
import 'package:riverpod_todo_list/todo_list_state.dart';
import 'package:state_notifier/state_notifier.dart';
import 'package:uuid/uuid.dart';
class TodoListNotifier extends StateNotifier<TodoListState> with LocatorMixin {
TodoListNotifier() : super(const TodoListState());
Uuid _uuid = Uuid();
// could not run.
#override
void initState() {
super.initState();
print('init state~~~');
}
// could not run.
#override
void update(Locator watch) {
super.update(watch);
print('update');
}
// could run.
void add(String title) {
Todo todo = Todo(id: _uuid.v4(), title: title);
List<Todo> todoList = []..addAll(state.todoList);
todoList.add(todo);
state = state.copyWith(todoList: todoList);
}
// could run.
void toggleStatus(int index) {
List<Todo> todoList = []..addAll(state.todoList);
todoList[index] = state.todoList[index]
.copyWith(completed: !state.todoList[index].completed);
state = state.copyWith(todoList: todoList);
print('changed toggle~~');
}
}
restarted logs
not put initState() and update() logs.
Performing hot restart...
Restarted application in 464ms.
flutter: start~~
The question is already answered on the Github.
LocatorMixin is not supported by Riverpod.
https://github.com/rrousselGit/river_pod/issues/75#issuecomment-671255330
And it's proposed to note it in the document.
In my opinion, LocatorMixin is not needed to use with Riverpod because of ProvidierReference.
final userRepositoryProvider = Provider((ref) => UserRepository());
final userControllerProvider = StateNotifierProvider((ref) {
return UserController(
// Read userRepositoryProvider and create a UserController from the result
repository: ref.watch(userRepositoryProvider),
);
});
Im doing a splashscreen first app, to be followed by a walkthrough page if the user first used the app, else go to a welcome page to sign in/ sign up if already saw the walkthrough screen.
My code came from this projects main.dart file: https://github.com/instaflutter/flutter-login-screen-firebase-auth-facebook-login and modified it to this code(from splashscreen tutorial FlutterKart)
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:binder/ui/screens/root_screen.dart';
import 'package:binder/ui/screens/walk_screen.dart';
void main() {
Firestore.instance.settings(timestampsInSnapshotsEnabled: true);
SharedPreferences.getInstance().then((prefs) {
SplashScreen(prefs: prefs);
});
}
class SplashScreen extends StatefulWidget {
final SharedPreferences prefs;
SplashScreen({Key key,this.prefs}): super(key: key);
#override
_SplashScreenState createState() => _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
#override
void initState() {
super.initState();
Timer(Duration(seconds: 3), () => _handleCurrentScreen(context));
}
#override
Widget build(BuildContext context) {
final logowhite = Hero(
tag: 'hero',
child: //code insert flutterkart splashscreen
)
],
),
)
],
)
],
),
);
}
Widget _handleCurrentScreen (BuildContext context) {
bool seen = (widget.prefs.getBool('seen') ?? false);
if (seen) {
return new RootScreen();
} else {
return new WalkthroughScreen(prefs: widget.prefs);
}
}
}
I want it to show the splashscreen first and directed to the rootscreen if already seen and to the walkthrough screen if first use.
You'd probably want to use shared_preferences or something similar. Something like this:
// add this static variable somewhere
// could technically be initialized during splash screen and added to a Provider or something similar after
static SharedPreferences prefs;
// make `main` async if it is not already
Future<void> main() async {
prefs = await SharedPreferences.getInstance();
...
}
Future<void> onSplashScreenDone() async {
if (prefs.getBool('isFirstTime') ?? true) {
// you might want to put this at the end of your walkthrough, so they don't miss it if they close the app, for example
await prefs.setBool('isFirstTime', false);
// this is their first time, show walkthrough, etc.
...
} else {
// this is not their first time, do normal things.
}
}
Im extending the native implementation of FirebaseMessagingService to wait for push notifications in native android.
I need to start my flutter app when the user clicks the push notification, so.. How can I send data to my flutter app?
In Flutter
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget{
#override
Widget build(BuildContext context) {
return MaterialApp(
home: ScreenPage(),
);
}
}
class ScreenPage extends StatefulWidget {
#override
_ScreenPageState createState() => _ScreenPageState();
}
class _ScreenPageState extends State<ScreenPage> {
static const platform = const MethodChannel("myChannel");
#override
void initState() {
platform.setMethodCallHandler(nativeMethodCallHandler);
super.initState();
}
Future<dynamic> nativeMethodCallHandler(MethodCall methodCall) async {
print('Native call!');
switch (methodCall.method) {
case "methodNameItz" :
return "This data from flutter.....";
break;
default:
return "Nothing";
break;
}
}
#override
Widget build(BuildContext context) {
//return ();
}
}
In Java
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import io.flutter.app.FlutterActivity;
import io.flutter.plugin.common.MethodChannel;
//import io.flutter.view.FlutterNativeView;
public class MyJavaFile extends FlutterActivity {
Button clickMeButton;
MethodChannel channel;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
channel = new MethodChannel(getFlutterView(), "myChannel");
setContentView(R.layout.home_activity);
clickMeButton = findViewById(R.id.clickMeButton);
clickMeButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
channel.invokeMethod("methodNameItz", null, new MethodChannel.Result() {
#Override
public void success(Object o) {
Log.d("Results", o.toString());
}
#Override
public void error(String s, String s1, Object o) {
}
#Override
public void notImplemented() {
}
});
}
});
}
}
You can still basically look at the firebase messaging example (or the same for android)
Create a Platform Channel in your AppDelegate (or MainActivity on android) and the register for the same channel on the dart/flutter side (maybe main.dart and register a method like onPushClicked)
Listen for your parse messages in your native code
Send them to your dart code using the platform channel (as seen in the above linked example) channel.invokeMethod('onPushClicked', myMessageArguments)
flutter
Map<String,dynamic> data = <String,dynamic>{};
final res = await methodChannel.invokeMethod('getDistance');
data = Map<String,dynamic>.from(res);
final dis = data['distance'] as String;
final tim = data['time'] as String;
ios native
switch call.method {
case "getDistance":
let data =
["distance":routeFormattedDistance,"time":routeFormattedTravelTime]
result(data)
default :
result("")
}