How to launch URL in Flutter? - url

NOTE: I've already searched for ages about this problem & read every similar problem on StackOverflow
I'm making Flutter app and I want to launch a URL on button click (Canvas based).
Everything was okay, until I used "url_launcher".
I'm using Flutter 1.13.6(Latest).
Below is the redirection function I'm using.
import 'package:url_launcher/url_launcher.dart' as URLLaucher;
abstract class URL {
static launchURL(String url) async {
url = Uri.encodeFull(url);
if (await URLLaucher.canLaunch(url)) {
await URLLaucher.launch(url);
} else {
throw 'Unknown error, can\'t launch the URL. Холбоост нэвтрэхэд алдаа гарлаа';
}
}
}
And this is the error log I'm gettin' when I run "flutter run" command.
FAILURE: Build failed with an exception.
* What went wrong:
A problem occurred configuring project ':url_launcher'.
> Could not resolve all artifacts for configuration ':url_launcher:classpath'.
> Could not download gradle.jar (com.android.tools.build:gradle:3.4.2)
> Could not get resource 'https://dl.google.com/dl/android/maven2/com/android/tools/build/gradle/3.4.2/gradle-3.4.2.jar'.
> Read timed out
> Could not download builder.jar (com.android.tools.build:builder:3.4.2)
> Could not get resource 'https://dl.google.com/dl/android/maven2/com/android/tools/build/builder/3.4.2/builder-3.4.2.jar'.
> Premature end of Content-Length delimited message body (expected: 31038805; received: 2359280
> Failed to notify project evaluation listener.
> Could not get unknown property 'android' for project ':url_launcher' of type org.gradle.api.Project.
> Could not find method implementation() for arguments [project ':url_launcher_web'] on object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler.
> Could not find method implementation() for arguments [project ':url_launcher_macos'] on object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler.
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org

this happens when you do a hot restart after you added something to your pubspec.yaml - just close the app and install it again

I had the same error.
So I upgraded flutter to v1.12.13 and used url_launcher5.3.0 and it worked.

pubspec.yaml
url_launcher: ^6.0.6
main.dart
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
const _url = 'https://flutter.dev';
void main() => runApp(
const MaterialApp(
home: Material(
child: Center(
// ignore: deprecated_member_use
child: RaisedButton(
onPressed: _launchURL,
child: Text('Bappa\'s apps in playstore'),
),
),
),
),
);
void _launchURL() async {
launch("https://play.google.com/store/search?q=pub%3ABAPPA%20SAIKH&c=apps" );
}

I used this syntax and worked for me
void _launchUrl() async {
if (!await launchUrl(_url)) throw 'Could not launch $_url';
}

Related

Expo TrackingTransparency failing when asking for permission

I'm building an app for iOS using Expo and I require the use of the TrackingTransparency. For some reason when I ask for the user permission it fails with the following error:
[Unhandled promise rejection: TypeError: undefined is not an object (evaluating '_ExpoTrackingTransparency.default.requestPermissionsAsync')]
at node_modules\expo-tracking-transparency\build\TrackingTransparency.js:31:7 in requestTrackingPermissionsAsync
at node_modules\regenerator-runtime\runtime.js:63:36 in tryCatch
at node_modules\regenerator-runtime\runtime.js:293:29 in invoke
at node_modules\regenerator-runtime\runtime.js:63:36 in tryCatch
at node_modules\regenerator-runtime\runtime.js:154:27 in invoke
at node_modules\regenerator-runtime\runtime.js:189:16 in PromiseImpl$argument_0
at node_modules\react-native\node_modules\promise\setimmediate\core.js:45:6 in tryCallTwo
at node_modules\react-native\node_modules\promise\setimmediate\core.js:200:22 in doResolve
at node_modules\react-native\node_modules\promise\setimmediate\core.js:66:11 in Promise
at node_modules\regenerator-runtime\runtime.js:188:15 in callInvokeWithMethodAndArg
at node_modules\regenerator-runtime\runtime.js:211:38 in enqueue
at node_modules\regenerator-runtime\runtime.js:238:8 in exports.async
at node_modules\expo-tracking-transparency\build\TrackingTransparency.js:5:41 in <global>
at node_modules\regenerator-runtime\runtime.js:63:36 in tryCatch
at node_modules\regenerator-runtime\runtime.js:293:29 in invoke
at node_modules\regenerator-runtime\runtime.js:63:36 in tryCatch
at node_modules\regenerator-runtime\runtime.js:154:27 in invoke
at node_modules\regenerator-runtime\runtime.js:189:16 in PromiseImpl$argument_0
at node_modules\react-native\node_modules\promise\setimmediate\core.js:45:6 in tryCallTwo
at node_modules\react-native\node_modules\promise\setimmediate\core.js:200:22 in doResolve
at node_modules\react-native\node_modules\promise\setimmediate\core.js:66:11 in Promise
at node_modules\regenerator-runtime\runtime.js:188:15 in callInvokeWithMethodAndArg
at node_modules\regenerator-runtime\runtime.js:211:38 in enqueue
at node_modules\regenerator-runtime\runtime.js:238:8 in exports.async
at node_modules\react-native-gradient-buttons\src\index.js:80:29 in <anonymous>
at node_modules\react-native\Libraries\Pressability\Pressability.js:691:17 in _performTransitionSideEffects
at node_modules\react-native\Libraries\Pressability\Pressability.js:628:6 in _receiveSignal
at node_modules\react-native\Libraries\Pressability\Pressability.js:524:8 in responderEventHandlers.onResponderRelease
at node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:265:4 in invokeGuardedCallbackImpl
at node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:476:2 in invokeGuardedCallback
at node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:500:2 in invokeGuardedCallbackAndCatchFirstError
at node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:597:41 in executeDispatch
at node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:621:19 in executeDispatchesInOrder
at node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:2521:28 in executeDispatchesAndRelease
at [native code]:null in forEach
at node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:836:4 in forEachAccumulated
at node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:2546:20 in runEventsInBatch
at node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:2702:18 in runExtractedPluginEventsInBatch
at node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:2639:35 in batchedUpdates$argument_0
at node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:17712:13 in batchedUpdates$1
at node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:2492:29 in batchedUpdates
at node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:2638:16 in _receiveRootNodeIDEvent
at node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:2767:27 in receiveTouches
at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:416:4 in __callFunction
at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:109:6 in __guard$argument_0
at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:364:10 in __guard
at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:108:4 in callFunctionReturnFlushedQueue
at [native code]:null in callFunctionReturnFlushedQueue
I installed the library as expo indicates here
Also, after I installed the library in my app.json appeared as a plugin
"plugins": [
"expo-tracking-transparency"
]
And when I start the app the log says:
Error: Problem validating fields in app.json. Learn more: https://docs.expo.io/workflow/configuration/
• should NOT have additional property 'plugins'.
But I'm not sure if that's a real issue or I can ignore it.
The question is, what else can I do to make the tracking transparency library work?
My code where I'm requesting the permission is the following:
const logInHandler = () => {
(async () => {
const w = await requestTrackingPermissionsAsync();
console.log(w);
const { status } = await requestTrackingPermissionsAsync();
if (status === 'granted') {
login();
} else {
dispatchAlertState({
action: SHOW_ALERT,
message:
'Permission is required in order to log in.',
type: AlertType.error,
});
}
})();
};
[EDIT]
I noticed that if I use the isAvailable() method from the expo-tracking-transparency library it says that the TrackingTransparency API is not available on the device, which is weird, because the simulator is an iPad running iOS 14.5, I also tested on an iPad mini 2 which runs iOS 12.5 it says it is not available (as expected), but the expo docs say the getTrackingPermissionsAsync() should always return true on older devices and Android.
[Edit 2]
If someone reads this and has the same problem, make sure to be using the expo V42, I was using the V40 which does not contain the code to get the permission

Dart testing Command line program

Suppose I have the following program increment.dart,
import 'dart:io';
void main() {
var input = int.parse(stdin.readLineSync());
print(++input);
}
and I want to test it similar to expect() from test package like,
test('Increment', () {
expect(/*call program with input 0*/ , equals(1));
});
Elaborating my use case:
I use this website to practice by solving the puzzles. They do have an online IDE but it doesn't have any debugging tools and the programs use std io. So what I have to do for debugging my code locally is to replace every stdin.readLineSync() with hardcoded test values and then repeat for every test. I'm looking a way to automate this.(Much like how things work on their site)
Following #jamesdlin's suggestion, I looked up info about Processes and found this example and whipped up the following test:
#TestOn('vm')
import 'dart:convert';
import 'dart:io';
import 'package:test/test.dart';
void main() {
test('Increment 0', () async {
final input = 0;
final path = 'increment.dart';
final process = await Process.start('dart', ['$path']);
// Send input to increment.dart's stdin.
process.stdin.writeln(input);
final lineStream =
process.stdout.transform(Utf8Decoder()).transform(LineSplitter());
// Test output of increment.dart
expect(
lineStream,
emitsInOrder([
// Values match individual events.
'${input + 1}',
// By default, more events are allowed after the matcher finishes
// matching. This asserts instead that the stream emits a done event and
// nothing else.
emitsDone
]));
});
}
Trivia:
#TestOn()
Used to specify a Platform Selector.
Process.start()
Used to run commands from the program itself like, ls -l (code: Process.start('ls', ['-l'])). First argument takes the command to be executed and second argument takes the list of arguments to be passed.
Testing stream

How to run exit-independent code in Dart?

I'm willing to execute pub get in background ignoring if the process that started it exited o terminated. Something like this:
// ... pubspec.yaml code changes
executeInBackground("pub get"); //async call, returns a Future
exit(0);
How could I do this without using the Process.runSync() blocking call? (I want the program to end ASAP)
See Process.start doc and its mode parameter.
import 'dart:io';
main() async {
final p = await Process.start(
'pub',
['get'],
runInShell: true,
mode: ProcessStartMode.DETACHED, //all the magic is here
);
print(p.pid);
}

How do I fail a script running in Bitbucket Pipelines?

When a pipeline runs a node series of commands, how can I trigger a fail within the pipeline?
I have tried the following:
const failBuild = function(message) {
console.error('Deploy failed: ', message)
throw new Error('Deploy failed')
}
I see the "Deploy failed" message, but the pipeline still says "Success".
Bb Pipelines fail when a command exits with a non-zero exit code. So, if you want the pipeline to fail, you have to make sure the code is not 0.
In your case (note for people reading this later: see comments), you get 0 as exit status, because the throw is executed in a promise, but then catched in the promise’s catch() function – which does neither stop execution nor have any influence on the exit code.
Solution: explicitly throw an error in the catch() function.
For anyone else who might be struggling with this...
You need to return a non zero as already mentioned, I find the easiest way to do this is by passing a negative integer to PHP's exit() function.
https://php.net/manual/en/function.exit.php
if($condition == true)
{
// Whatever we were doing, it worked YAY!!
exit();
}
else
{
// Something went wrong so fail the step in the pipeline
exit(-1);
}
The accepted answer states:
Solution: explicitly throw an error in the catch() function.
So if I understand that correctly, it suggests you should write the script as:
async function main() { throw "err"; }
main().catch(e => { throw e; });
However, this does not work: the exit code is still 0, and the console displays a nasty warning:
> node "main.js"
(node:32996) UnhandledPromiseRejectionWarning: err
(node:32996) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)
(node:32996) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
> $?
0
The correct way to bubble up the error to the node process is:
process.on('unhandledRejection', up => { throw up });
async function main() { throw "err"; }
main();
This way, you get teh following result:
> node "main.js"
test2.js:1
process.on('unhandledRejection', up => { throw up });
^
err
> $?
1
Which is a little bit better (except the stacktrace is not very clear).

Test is failing even though expectations are met

I have a test that looks like this:
test('should throw error if threshold is null', (){
final findEngine = new FindEngine<Foo>();
expect(findEngine.streamResults('foo', null), throwsA(new
isInstanceOf<ThresholdNullOrOutOfBoundsError>()));
});
The test is failing with the following message:
ERROR: should throw error if threshold is null
Test failed: Caught Instance of 'ThresholdNullOrOutOfBoundsError'
Am I doing something wrong here?
Figured it out. Needed to close over the call that I expected to fail:
expect(() => findEngine.streamResults('foo', null), throwsA(new
isInstanceOf<ThresholdNullOrOutOfBoundsError>()));

Resources