MediaStore.Images.Media.LATITUDE and MediaStore.Images.Media.LONGITUDE was deprecated in Android Q.
Does anyway know how we can get the Media location on React Native with expo? Basically do the below without Ejecting.
Android 10: fetch the gallery via MediaStore with location information
Thank you
import * as Permissions from 'expo-permissions';
import * as MediaLibrary from 'expo-media-library';
import Exif from 'react-native-exif'
...
MediaLibrary.getAssetInfoAsync(asset).then(function (e) {
console.log("Location is ", e.location); //always null
if (e.location) {
data.push(e);
}
});
Exif.getLatLong(asset) //doesn't get location.
.then((loc) => { console.log('Location OK: ', loc) })
.catch(msg => console.log('messages: ' + msg))
This may be an issue if you're using a real device and not an emulator.
When I use the iOS simulator, there are no issues getting the location with this method, if the image contains any location data.
const imageData = await MediaLibrary.getAssetInfoAsync(assetId);
console.log(imageData.location)
How ever, on my physical android device the locations field also resolves to null.
Even though the image i'm testing with is the same.
But when I use expo ImagePicker, location is shown if the image contains the informations.
Also, it may be unnecessary to use react-native-exif; the method getAssetInfoAsync already returns the image EXIF data.
Related
I'm currently building a simple app in React Native 0.62.2 for Android. I've been having some trouble with axios 0.19.2 (or even the fetch API) when trying to upload images to my API (which is written in node.js/express). The POST request is formulated as follows:
// UserService.js
export const postNewUser = async (newUser) => {
try {
const photo = {
uri: newUser.avatar.uri,
type: 'image/jpg',
name: newUser.avatar.fileName,
};
const formData = new FormData();
Object.keys(newUser).forEach(key => formData.append(key, newUser[key]));
formData.append('avatar', photo);
const response = await api.post('/users', formData);
return response.data;
} catch (err) {
console.log('TRACE error posting user: ', err);
return;
}
}
Here, the property newUser.avatar.uri is set by means of an image picker library, namely #react-native-image-picker 1.6.1. It gives me a NetworkError whenever I append the photo variable into the FormData. Setting the URI manually with some random image from the web results in the same error. Debbuging it from the Browser, it prints out some sort of stack trace like this one:
TRACE error posting user: Error: Network Error
at createError (C:\Users\Dell\Documents\Projetos\SmartestVet\node_modules\axios\lib\core\createError.js:16)
at EventTarget.handleError (C:\Users\Dell\Documents\Projetos\SmartestVet\node_modules\axios\lib\adapters\xhr.js:83)
at EventTarget.dispatchEvent (C:\Users\Dell\Documents\Projetos\SmartestVet\node_modules\event-target-shim\dist\event-target-shim.js:818)
at EventTarget.setReadyState (C:\Users\Dell\Documents\Projetos\SmartestVet\node_modules\react-native\Libraries\Network\XMLHttpRequest.js:575)
at EventTarget.__didCompleteResponse (C:\Users\Dell\Documents\Projetos\SmartestVet\node_modules\react-native\Libraries\Network\XMLHttpRequest.js:389)
at C:\Users\Dell\Documents\Projetos\SmartestVet\node_modules\react-native\Libraries\Network\XMLHttpRequest.js:502
at RCTDeviceEventEmitter.emit (C:\Users\Dell\Documents\Projetos\SmartestVet\node_modules\react-native\Libraries\vendor\emitter\EventEmitter.js:189)
at MessageQueue.__callFunction (C:\Users\Dell\Documents\Projetos\SmartestVet\node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:425)
at C:\Users\Dell\Documents\Projetos\SmartestVet\node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:112
at MessageQueue.__guard (C:\Users\Dell\Documents\Projetos\SmartestVet\node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:373)
If I, for example, comment out the line formData.append('avatar', photo); it works perfectly, i.e., my API receives the request accordingly. So I think this might not be a CORS-related issue. Also, other requests, such as GETs and even other POSTs are working just fine.
I know there's a bunch of other related posts here in SO and also in GitHub, some of them related to the exact same issue. But none of the solutions I found worked out for me.
In case someone wants to check out how the routes in my API are implemented just hit me up and I will provide the code here.
Thanks in advance for any help you might give me!
I'm having the same issue, using the formData but without the file upload it works just fine. I did a lot of research and what I've found is an old issue that still's active in the react native repo. The solution that's suggested is using a library called rn-fetch-blob but I couln't implement it on my project. If you can make it work share your work around please.
I have a problem using Geolocation on Android device.
I create an Ionic 3 application.
I use Geolocation ( [https://ionicframework.com/docs/native/geolocation/ 13]).
I use the sample code provided there.
The problem is that, the code works in Browser but whenever I upload it on an Android device, it does not work.
When I start the app on device the alert for location permission is prompted.
I press Allow.
Then in the android tray an icon appears that says “Searching for GPS”.
After timeout expires I got the error for timeout and no location.
The strange think is this:
If I close my app, then open google maps ( or other app using gps position ) and reopen my app works as it should.
I don’t know what to do.
The permissions are fine :
and everything was installed properly.
Can anyone help please?
i got it actually i have to pass apikey with that like
<script src="http://maps.googleapis.com/maps/api/js?key=YOUR_KEY"></script>
in the index page
without this key it sometime works but not sure everytime.
Note : this key is only generated when you have a valid gmail a/c (by providing DOB/CreditCard nos) although its free .
try this, it should work
ionic cordova run android --prod
--prod makes production build apk
import { LocationAccuracy } from '#ionic-native/location-accuracy';
declare var navigator
Above
#Component
watchPosition() {
this.locationAccuracy.request(this.locationAccuracy.REQUEST_PRIORITY_HIGH_ACCURACY).then(
() => {
var options = {
timeout: 500,
maximumAge: Infinity
};
this.watch = navigator.geolocation.watchPosition((data) => {
let latlng: LatLng = new LatLng(data.coords.latitude, data.coords.longitude);
}, (error) => {
console.log("error watch", error)
}, options);
}
}, error => {
alert('Error requesting location permissions' + JSON.stringify(error))
});
}
}
This library allows you to get unique device id / Mac address of Android devices, which doesn't change after reinstallation.
Expo.Constants.deviceId changes after every reinstallation (even if the app version number is the same).
Is there a way to get an unique id for Android that doesn't change after reinstallation (at least for if it's the same version), without ejecting?
For Expo IOS theres currently very limited options, Since Apple forbids getting private device info. We will need to create our own unique identifier below.
Solution:
My solution is a combination of uuid and Expo SecureStore works for IOS and Android.
import * as SecureStore from 'expo-secure-store';
import 'react-native-get-random-values';
import { v4 as uuidv4 } from 'uuid';
let uuid = uuidv4();
await SecureStore.setItemAsync('secure_deviceid', JSON.stringify(uuid));
let fetchUUID = await SecureStore.getItemAsync('secure_deviceid');
console.log(fetchUUID)
This solution will work even if app gets reinstalled, or if user switches devices and copy's all data to new device.
(Expo.Constants.deviceId is deprecated and will be removed in Expo SDK 44).
Full Example:
To check if you already stored the uuid in SecureStore
import * as SecureStore from 'expo-secure-store';
import 'react-native-get-random-values';
import { v4 as uuidv4 } from 'uuid';
let uuid = uuidv4();
let fetchUUID = await SecureStore.getItemAsync('secure_deviceid');
//if user has already signed up prior
if (fetchUUID) {
uuid = fetchUUID
}
await SecureStore.setItemAsync('secure_deviceid', JSON.stringify(uuid));
console.log(uuid)
Use Application.androidId from expo-application. Id will not change after reinstall or update. The value may change if a factory reset is performed on the device or if an APK signing key changes.
https://docs.expo.dev/versions/latest/sdk/application/#applicationandroidid
Example:
import * as Application from 'expo-application';
import { Platform } from 'expo-modules-core';
import * as SecureStore from 'expo-secure-store';
import Constants from 'expo-constants';
const getDeviceId = async () => {
if (Platform.OS === 'android') {
return Application.androidId;
} else {
let deviceId = await SecureStore.getItemAsync('deviceId');
if (!deviceId) {
deviceId = Constants.deviceId; //or generate uuid
await SecureStore.setItemAsync('deviceId', deviceId);
}
return deviceId;
}
}
Guess you can use facebook module for this purpose.
https://docs.expo.io/versions/latest/sdk/facebook-ads/#currentdevicehash
Not sure what happens under hood - but looks like it unique between app reinstal, device restart etc.
Just use getuniqueid() method from react-native-device-info. Works on iOS and android to uniquely identify a device .
To get the device UniqueId in expo project,
npm install react-native-device-info
expo run:ios or expo run:android
Please note: expo start will throw an error
Anybody success to use the plugin cordovaFile & cordovaFileTransfer?
I have failed to understand and failed miserably execution. Case wants to make the upload and download controller. Each tested via the browser, it always appears File / FileTransfer is not defined in Firebug. When I made to console.log as:
console.log($cordovaFile); or
console.log($cordovaFileTransfer); or
console.log($cordovaFileTransfer.download); or
console.log($cordovaFileTransfer.upload);
Its return true, form of the {object}.
But when I call their methods included parameters, for example:
$cordovaFileTransfer.download (urlServer, fileTarget, {}, true);
Direct emerge error: FileTransfer is not defined.
I tried to move the download function to the Service, and then Controller call the function (the umpteenth time search results on google). The result is just the same, the above error.
Because there are user in some forum said should / could only be tested through the device, finally I try to upload ionic.io & I sync via APL ionic view on my Smartphone. But the result is NOTHING.
I tried to improvise a little, try method checkDir / checkFile as follows:
.controller('PhotoCtrl', function($scope, $cordovaFile) {
$scope.downpic = function(){
$cordovaFile.checkDir("/sdcard/storage/emulated/0/").then(function(result){
alert("wow");
}, function(err){
alert("eror");
});
}
})
It turns out alerts that appear "error", I try mutually value directory is as follows:
file///sdcard/storage/emulated/0/
file///storage/emulated/0/
/storage/emulated/0/
Just the same error alerts, the chain problem. My question :
What is the application of ionic cordova can access the internal
storage? (I only have the Mobile Internal Storage, without External
Storage);
I was looking for information about AndroidManifest.xml
uses-permission, the permission is only for external storage. Are
there any other analysis?
Please help, really newbie
Finally, I just got the clear solution from the link below :
https://www.thepolyglotdeveloper.com/2014/09/manage-files-in-android-and-ios-using-ionicframework/
I am trying to check disk space available in mobile using below code:
cordova.exec(function(result) {
var diskSizeInMB = result/1024;
alert(diskSizeInMB)
}, function(error) {
alert("Error: " + error);
}, "File", "getFreeDiskSpace", []);
In Android device it gives me correct result, whereas if I use iPhone/iPad it always returns me 0 as a output. Can anyone guide me how to resolve this issue? Or is there a way to check the disk size in iOS using cordova without writing custom plugin? To make this happen I haven't changed any configuration changes
It was a bug, but was fixed long time ago.
Old answer:
I confirm there is a bug on the code, the problem is getFreeDiskSpace is undocumented and cordova team want to remove the native code as getFreeDiskSpace isn't part of the w3c file API.
If you want to fix the bug for you app, go to CDVFile.m and change the line
NSNumber* pNumAvail = [self checkFreeDiskSpace:self.appDocsPath];
to
NSNumber* pNumAvail = [self checkFreeDiskSpace:self.rootDocsPath];
on the getFreeDiskSpace method