Xamarin: Differences in async handling on Android and UWP - android

When using async Methods of PCLStorage there is a strange behaviour on UWP.
In the Constructor of App I have to load a json file by PCLStorage. The first file Operation is a CheckFileAsync. As the App constructor is not an async method (it's ok if it blocks for a moment) I first tried this:
var catalogue =FreshTinyIOCBuiltIn.Current.Resolve<IStorageManager>().GetCatalogue(null).Result;
Which works fine on Android. But on UWP it blocks completely and never comes back.
If I do it this way:
Catalogue catalogue = null;
var t = Task.Run(async () =>
{
catalogue = await FreshTinyIOCBuiltIn.Current.Resolve<IStorageManager>().GetCatalogue(null);
});
t.Wait();
Everything is fine. What is the reason for this?

Related

Calling Firebase cloud function causes DEADLINE_EXCEEDED error when using Firebase emulator

I've got a very simple cloud function that returns a string in a JSON.
const functions = require("firebase-functions");
// Create and Deploy Your First Cloud Functions
// https://firebase.google.com/docs/functions/write-firebase-functions
exports.helloWorld = functions.https.onRequest((request, response) => {
functions.logger.info("Hello logs!", {structuredData: true});
response.send({data: "Hello from Firebase!"});
});
And I am calling it like this(app is running in android emulator):
async function callFirebaseCloudFunction() {
try
{
functions().useEmulator('localhost', 5001);
const helloWorldFunction = functions().httpsCallable('abcd');
const response = await helloWorldFunction();
console.log(response?.data);
alert(response?.data);
}
catch (error)
{
console.log("====",error);
alert(`${JSON.stringify(error)}` );
}
}
The issue is that I am getting DEADLINE_EXCEEDED error.
Note that I am also running firebase's emulator for cloud function, therefore this line:
functions().useEmulator('localhost', 5001);
Otherwise, commenting the above line and calling the deployed function works fine.
After spending more than an hour, and writing this question. I finally figured out the problem(kind of), so I thought I should just answer it.
I was using the android emulator of Genymotion, and the request kept failing "DEADLINE_EXCEEDED" error. When I used avd(android virtual device from Android Studio), it worked totally fine.

Expo IntentLauncher.startActivityAsync with android.intent.action.VIEW

I created an app with expo where some report in xlsx is generated in a server and then downloaded to the Download folder in Android. I want to "open" the file after it was downloaded by using another app with the open with native modal. I tried the following:
static openFile = async (asset, contentType) => {
return IntentLauncher.startActivityAsync('android.intent.action.VIEW', {
data: asset.uri,
type: contentType,
});
};
(contentType is currently receiving '*/*') but it fails everytime with the following error:
Encountered an exception while calling native method: Exception occurred while executing exported method startActivity on module ExpoIntentLauncher: file:///storage/emulated/0/Download/report-10010654-20210304061930069176.xlsx exposed beyond app through Intent.getData()
One solution is using the Sharing library, but I'm not overjoyed with it. Is there any way to make it work without ejecting from the managed flow?
I had a similar problem a month ago, I think it happens when startActivityAsync is called multiple times, my solution was to wrap my code in a try statement:
const data = await getContentUriAsync(uri)
try {
await startActivityAsync('android.intent.action.VIEW', { data, flags: 1 })
} catch (error) {}

Protractor locators does not work in PageObjectModel structure

Framework: Appium + Protractor + Cucumber + Typescript using POM model
I have the protractor framework for appium designed in POM structure
The initial page of the app will identify the locators calling in a different ts file and the functions such as tap, isDisplayed calling it in a different ts file.
But once it passes the initial pages in the app,say 3 pages. the locators are not identified which are calling other function, but they are identified when they are passed directly ( like driver.findelements(by.css('')).click ) this works.
The problem is I can't pass this code like this within the step definition .ts file always as it is not a good structure
Note: By the way, this script was working fine earlier.
tried to test using a different workaround, like building the binary again, trying to run on android and ios application, downgrading or upgrading the node packages. But nothing solved the problem. has anyone faced this kind of issue. Any suggestions or solutions for this problem, please?
Code which works: (Passing the locators directly in the function, rather than from the onboarding.ts file will work)
Then(/^VIC should be selected from the state or territory drop down$/, async () => {
await browser.driver.findElement(by.css('button[sp-automation-id=\'select-state-toggle\']')).click();
await browser.driver.findElement(by.css('page-action-sheet label[sp-automation-id=\'action-sheet-option-VIC\']')).click(); });
Code which does not work: (Onboarding.ts file contains the locators defined for State and VIC same as the above code block. But reading from there it does not work.)
Then(/^VIC should be selected from the state or territory drop down$/, async () => {
await AutomationAction.tap(Onboarding.State);
await AutomationAction.tap(Onboarding.VIC); });
Code which works (The below code is called before the above code block, it's a page before calling the above pages)
Then(/^I enter the mobile number and tap next button on the your mobile number screen$/, async () => {
MobileNo = AutomationAction.getMobileNumber("mobileNumber");
SameMobileNo = MobileNo;
await AutomationAction.sendKeyText(Onboarding.InputMobileNo,MobileNo);
await AutomationAction.tap(Onboarding.Next_BTN_YourMobileNumber);
});
Because of the page where it is failing the automation thinks its as non-angular page and the locators used to fail or not locate them when calling it in a different function. When I introduced browser.ignoreSycnhronization=true to make Angular sync for non-angular apps/pages it worked.

React native android undefined is not a function works in IOS

Works in IOS and works in Android when the debugger is running, but doesn't work via Android Simulator. I get this message via react-native log-android and basically I am just having nothing returned to the screen:
12-02 10:39:58.511 22502 24204 W ReactNativeJS: TypeError: undefined is not a function (near '...}).flat()
Android Picture
IOS Picture
Here is the fetch function I am using:
import axios from 'axios';
export const getData = async url => {
try {
const response = await axios.get(url);
const data = response.data;
return data;
} catch (error) {
console.log(error);
}
};
export default getData;
Inside of my componentDidMount, where I call the endpoint using the GetData function above:
componentDidMount() {
const teamsAPI = 'https://statsapi.web.nhl.com/api/v1/teams';
getData(teamsAPI).then(teams => {
const teamData = teams.teams
.map(({ id, name }) => ({
teamId: id,
teamName: name
}))
.flat()
this.setState({
teams: teamData
});
});
}
Everything has since been moved to REDUX, but I looked back at one of my branches today with the more basic code shared above and had the issue back then with this code as well. Unfortunately didn't realize all the differences with code compilations till now. Understand that the issue is probably because of 2 compilers, but have no idea how to approach the issue/ why there would be a type error in one and not the other.
It works with debugger I think due to what was mentioned here:
React Native behavior different in simulator / on device / with or without Chrome debugging
Edit: wanted to mention I've already done a cache reset and deleted the build folder and rebuilt
I tried out your code and the promise rejecting is happing for me in both Android and iOS. It is being caused by the .flat() removing it stops the promise rejection from occurring.
Looking at the data that you are mapping there there doesn't seem to be a need to flatten the data as it comes back as a array of objects with no other arrays inside it.
Could removing the .flat() be a possible solution for you?
You can see here for more information about .flat() and how it is still experimental array.prototype.flat is undefined in nodejs
I would also consider returning something from your getData function when it makes an error or perhaps use a promise with it that way you can handle an error.

Fetch not working on React Native Android debug

I'm trying to create a very simple ReactNative app to play around with GraphQL and RN on an Android (I'm already familiar with getting it to work on an iPhone).
But I'm running into a problem -- my root component places a get request to an API. Although that request works perfectly when I spin up an XCode simulator, it completely fails when I run the Android version on my phone.
The Android/iOS versions are for now completely identical. The two index files both use react-native-router-flux and are identical, and they import shared components.
Here's the simplified code of the component:
constructor(props) {
super(props);
this.state = {
source: 'myGraphQLEndpoint'
}
}
componentDidMount() {
if (this.props.drill) { return null; }
this.serverRequest = fetch(this.state.source)
.then((result) => result.json())
.then((json) => {
this.setState({
drill: json.data.drill
});
});
}
componentWillUnmount() {
this.serverRequest.abort();
}
render() {
const { drill } = this.state;
if (!drill) { return null; }
... some view stuff
}
On my iOS simulator, this works perfectly. On my Android phone, it never sets state, and so doesn't get past the if (!drill) line. If I instead set the state to the expected API data directly (instead of making an actual call), the Android app works just fine (with the non-live data).
The phone IS connected to the internet.
Any idea what's wrong?
PS -- I've tried a number of variants, including:
Changing the request to have only one .then, which calls response.json().data.drill.
Assigning the response to a variable defined outside of the request, and setting state to equal that (which sets state to what looks like a response buffer [42, 36, ... which can't be printed to the screen.
No dice.

Categories

Resources