Is it possible to open the contacts on a device from an icon tap in flutter? I am able to open the phone function using url_launcher's plugin.I have used the contacts plugin but we dont have a need to manage contacts from our application, we want to use the phones functionality for managing contacts.
You can achieve this using Flutter platform channels and android Intent.ACTION_VIEW intent.
For example in your MainActivity register new channel and launch Contacts activity:
MethodChannel(flutterView, CHANNEL).setMethodCallHandler { call, result ->
launchContactActivity()
}
private fun launchContactActivity() {
val intent = Intent(Intent.ACTION_VIEW)
intent.type = ContactsContract.Contacts.CONTENT_TYPE
startActivityForResult(intent, REQUEST_CODE)
}
And on flutter side:
void launchContacts() async {
try {
await platform.invokeMethod('launch');
} on PlatformException catch (e) {
print("Failed to launch contacts: ${e.message}");
}
setState(() {
});
}
Please see full example. Hope this help.
Probably you can't directly.
But you can fetch them and their info with contacts_service package.
Hope this could help you.
Related
According to the Flutter's official deep linking page, we do not require any plugin or native Android/iOS code for handling deep links.
But it doesn't really tell us how we can get the data from that link. I'm talking from coding perspective. Sure, they have written in there that:
But this does not tell me where should I write what code to actually get the complete link. I've looked for examples/tutorials but I'm unable to find anything that is not using a plugin for handling deep linking.
Right now, all I've done is add <intent-filter> tags in AndroidManifest.xml file and on clicking the link, my app has started to show up. But I don't know how to extract data from that link.
Is there anyone who can guide me here? Thanks in advance.
You need platform specific code to handle deep linking. If you follow link mention in documention, you will find complete example.
private val CHANNEL = "poc.deeplink.flutter.dev/channel"
private var startString: String? = null
override fun configureFlutterEngine(#NonNull flutterEngine:FlutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine)
MethodChannel(flutterEngine.dartExecutor, CHANNEL).setMethodCallHandler { call, result ->
if (call.method == "initialLink") {
if (startString != null) {
result.success(startString)
}
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val intent = getIntent()
startString = intent.data?.toString()
}
Flutter Code:
class DeepLinkBloc extends Bloc {
//Event Channel creation
static const stream = const
EventChannel('poc.deeplink.flutter.dev/events');
//Method channel creation
static const platform = const
MethodChannel('poc.deeplink.flutter.dev/channel');
StreamController<String> _stateController = StreamController();
Stream<String> get state => _stateController.stream;
Sink<String> get stateSink => _stateController.sink;
//Adding the listener into contructor
DeepLinkBloc() {
//Checking application start by deep link
startUri().then(_onRedirected);
//Checking broadcast stream, if deep link was clicked in opened appication
stream.receiveBroadcastStream().listen((d) => _onRedirected(d));
}
_onRedirected(String uri) {
// Here can be any uri analysis, checking tokens etc, if it’s necessary
// Throw deep link URI into the BloC's stream
stateSink.add(uri);
}
#override
void dispose() {
_stateController.close();
}
Future<String> startUri() async {
try {
return platform.invokeMethod('initialLink');
} on PlatformException catch (e) {
return "Failed to Invoke: '${e.message}'.";
}
}
}
Follow this link for more detail.
https://medium.com/flutter-community/deep-links-and-flutter-applications-how-to-handle-them-properly-8c9865af9283
The Flutter way to do that, assuming you've already made the steps in the guide you posted, is to create a onGenerateRoute and/or onGenerateInitialRoutes handlers in your MaterialApp so that these handlers deals with the routes passed or pushed by the framework according to the described behaviors. You can even create an expected named route coming from a deeplink on the routes property of MaterialApp, even though I believe the dynamic generation of routes is more appropriate due to the dynamic nature of deeplinking, specially if you're dealing with "authentication needed content" inside your app.
Or, if you don't want to pass trough the platform specific code, you could use firebase dynamic links. That would allow to easily listen to links coming from both platforms and you also get the advantage that your link would bring up the store listing page if the user doesn't have the app installed.
I've written a full example here: https://gbaccetta.medium.com/flutter-deep-linking-with-firebase-dynamic-links-and-bloc-architecture-660f0517fbc2
Do for android as said in the web page: "Add a metadata tag and intent filter to AndroidManifest.xml inside the tag with the ".MainActivity" name". Do what required for ios too.
Then use onGenerateRoute in the usual way in MaterialApp, don't use "routes:". For example:
onGenerateRoute: (settings) {
print("settings.name " + settings.name.toString());
if (settings.name == '/') return MaterialPageRoute(builder: (_) => ScreenStart());
return MaterialPageRoute(builder: (_) => ScreenUnknown());
},
Then to simulate I did:
cd /Users/Utente/AppData/Local/Android/Sdk/platform-tools
adb shell
am start -W -a android.intent.action.VIEW -c android.intent.category.BROWSABLE -d "http://theaddressichoosed.com/helloworld?byebye"
And
print("settings.name " + settings.name.toString());
printed
settings.name /helloworld?byebye
After spending some time on this, here's my take using the Navigator 2 API. It also shows how to perform query and path arguments parsing. Hope it will save someone the time I spent researching this.
Obviously you also need to edit your platform-specific build files (such as AndroidManifest.xml for Android) as shown in the Flutter Deep Linking page.
A special note for Android 12 and above: you'll also need to securely approve the app's domain in the Google Play Developer Console for deep linking to work.
class App extends StatelessWidget {
const App({super.key});
#override
Widget build(BuildContext context) => MaterialApp(
initialRoute: '/',
routes: {
'/': (context) => HomeScaffold(),
'/route1': (context) => const RouteOneScaffold(),
'/route2': (context) => const RouteTwoScaffold(),
// Other routes which don't need any sort of query parsing
},
onGenerateRoute: (settings) {
// This is executed to determine which route to follow if no adequate entry is found in the `routes` array above.
// Here we can parse path and query parameters as we like.
final fullRoute = settings.name;
if (fullRoute == null) {
return null;
}
final routeData = Uri.tryParse(fullRoute);
if (routeData == null) {
return null;
}
final pathParameters = routeData.pathSegments;
final queryParameters = routeData.queryParameters;
// Here you can write your route handling logic
return MaterialPageRoute(builder: (context) => RouteThreeScaffold(pathParameters,queryParameters));
},
);
}
I want to Ignore Battery Optimization in our Ionic App, I have read about https://developer.android.com/reference/android/Manifest.permission#REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
For this I have added cordova-plugin-power-optimization Plugin that will add <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/> in AndroidManifest.xml,
Now I want to send Intent https://developer.android.com/reference/android/provider/Settings#ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS for the user to go to settings screen where he can exclude battery optimization,
I am not sure how to achieve this with Ionic WebIntent plugin, which we generally use to send/receive Intents
So far I am trying this code but not sure how to set Options and startActivity
Can anyone help please, I am using Ionic 4 with Cordova 7.1.4
this.androidPermissions.checkPermission(this.androidPermissions.PERMISSION.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)
.then((result) => {
alert('Has permission?'+result.hasPermission)
this.androidPermissions.requestPermission(this.androidPermissions.PERMISSION.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)
.then((data)=>{
alert('request permission then' + data.hasPermission);
//what should go here in options and startActivity
const openOptions = {
action: this.webIntent.ACTION_VIEW,
url: packageFileUrl,
type: 'application/vnd.android.package-archive'
};
this.webIntent.startActivity(openOptions).then((data1)=>{alert('data:'+data1)});
})
.catch((data)=>{
alert('request permission catch'+data.hasPermission)
})
},
);```
I am able to send Intent through WebIntent, Its just I need to use Constant value
"android.settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" in Action part of Intent Options, This constant values are mentioned on
https://developer.android.com/reference/android/provider/Settings#ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
Also for url, I have used getPackageName() method of AppVersion Plugin and pass this in url section of Intent Options,Here appName contains package Name and getPackageName() method is called from constructor.
Also Type is not needed here.
private async IntentIgnoreBatteryOptimization(resolve, reject) {
const openOptions = {
action:'android.settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS',
url: 'package:'+this.appName
};
try{
resolve(await this.webIntent.startActivity(openOptions));
}
catch(err){
reject('Permission denied'+err);
}
}
async getPackageName(){
if (this.device.isVirtual !== null) {
await this.appVersion.getPackageName().then((result)=>{
this.appName = result;
})
}
}
I think we can achieve this scenario by using the ionic Cordova native settings, in which you can pass battery_optimization and the native device will lead you to the battery optimization area.
I want to set up a mobile application with flutter which also runs in the background. this application allows you to scan Bluetooth devices and listen to events to launch notification and/or start a ringtone.
I managed to do all this and it works very well with the flutter_blue plugin. But my problem is that the application has to keep running in the background.
I came here to seek help.
The app does exactly what this app does https://play.google.com/store/apps/details?id=com.antilost.app3&hl=fr&gl=US
There are 2 ways to do it.
All you have to do that is write a native code in JAVA/Kotlin for android and obc-c/swift for ios.
The best place to start with this is here
If you just follow the above link then you will be able to code MethodChannel and EventChannel, which will be useful to communicate between flutter and native code. So, If you are good at the native side then it won't be big deal for you.
// For example, if you want to start service in android
// we write
//rest of the activity code
onCreate(){
startBluetoothService();
}
startBluetoothService(){
//your code
}
//then, For the flutter
// Flutter side
MessageChannel msgChannel=MessageChannel("MyChannel");
msgChannel.invokeMethode("startBluetoothService");
// Native side
public class MainActivity extends FlutterActivity {
private static final String CHANNEL = "MyChannel";
#Override
public void configureFlutterEngine(#NonNull FlutterEngine flutterEngine) {
super.configureFlutterEngine(flutterEngine);
new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL)
.setMethodCallHandler(
(call, result) -> {
if (call.method.equals("startBluetoothService")) {
int response = startBluetoothService();
//then you can return the result based on the your code execution
if (response != -1) {
result.success(response);
} else {
result.error("UNAVAILABLE", "Error while starting service.", null);
}
} else {
result.notImplemented();
}
}
);
}
}
same as above you can write the code for the iOS side.
Second way is to write your own plugin for that you can take inspiration from alarm_manager or Background_location plugins.
I hope it helps you to solve the problem.
I have created a custom document provider for Android using this code as a base.
https://learn.microsoft.com/en-us/samples/xamarin/monodroid-samples/storageprovider/
This allows for a new drive to be mapped onto the documents folder when browsing/saving documents.
If there is an exception due to a password timeout for example, I would like to pop back up the existing app so the users can entered their credentials again to log in.
Is this possible? As an example of what I am looking for, if the QueryRoots failed with a particular exception, could I run something to pop back up the app interface here?
public override ICursor QueryRoots(string[] projection)
{
Log.Verbose(TAG, "queryRoots");
var result = new MatrixCursor(ResolveRootProjection(projection));
try
{
if (!IsUserLoggedIn())
{
return result;
}
MatrixCursor.RowBuilder row = result.NewRow();
... other init code here
}
catch (Exception ex)
{
if (ex.Message == "NoSessionException")
{
// LOGIC TO BRING BACK APP TO LOG IN AGAIN HERE...
}
}
return result;
}
I make a sample code about how to lauch the app again for your reference. You could put Launch method in catch statement.
In Xamarin.Forms, you could use Dependency service to start the app with package name.
Create a interface:
public interface IDpendencyService
{
Task<bool> Launch(string stringUri);
}
Implemention of Android:
public class DependencyImplementation : Activity, IDpendencyService
{
public Task<bool> Launch(string stringUri)
{
Intent intent = Android.App.Application.Context.PackageManager.GetLaunchIntentForPackage(stringUri);
if (intent != null)
{
intent.AddFlags(ActivityFlags.NewTask);
Forms.Context.StartActivity(intent);
return Task.FromResult(true);
}
else
{
return Task.FromResult(true);
}
}
}
Register in MainActivity:
DependencyService.Register<IDpendencyService, DependencyImplementation>();
I use a Button event to invoke. You could try to invoke in catch.
DependencyService.Get<IDpendencyService>().Launch("com.companyname.xamarindemo");
Screenshot: I have a button on Page21. When i click the button, it would reload the app and pop back up the existing app.
How can I detect if the user creating a screenshot?
I do not care about the capture pictures, I just want to know when and where user creating the screenshot
How can I detect this in the flutter app?
You can try this plugin, it might be what you are looking for: https://pub.dev/packages/screenshot_callback
In order to accomplish what you are looking for from the README:
import 'package:screenshot_callback/screenshot_callback.dart';
ScreenshotCallback screenshotCallback = ScreenshotCallback();
screenshotCallback.addListener(() {
//Void funtions are implemented
print('detect screenshot');
});
try
https://pub.dev/packages/screenshot_callback
dependencies:
screenshot_callback: ^1.1.3
void init() async {
await initScreenshotCallback();
}
//It must be created after permission is granted.
Future<void> initScreenshotCallback() async {
screenshotCallback = ScreenshotCallback();
screenshotCallback.addListener(() {
setState(() {
text = "Screenshot callback Fired!";
});
});
screenshotCallback.addListener(() {
print("We can add multiple listeners ");
});
}