We have been happily developing our app using Service Workers because of the ease of building an offline app.
It's registered in the usual way:
navigator.serviceWorker.register( "./worker.js" ).then( function () {
console.log( "woohoo!" );
}, function ( err ) {
console.log( "oh noes", err );
});
And it is actually quite simple:
self.addEventListener( "install", function () {
console.log( "yay" );
});
It works fine while developing in the desktop browser, behind a web server.
But is there a way to use it while in Cordova/Crosswalk, as they use the file protocol?
Related
I have been working on a mobile app for the past year, and are preparing to deploy to production. Our app is used for sending applications for a certain license, and some users may be required to upload images in their application.
This feature has been implemented and working for many months, and given us no issues. However, now the Android version of the app is causing problems. When we submit the application, the fetch request to the endpoint is initiated, but never actually hits (only if images are included in the application).
Here is the code where the images are handled:
const xhr = new XMLHttpRequest()
xhr.responseType = 'blob'
xhr.onload = () => {
const file = xhr.response
const extension = file.type.split('image/').pop()
const fileName = `${field.identifier}-${docCounter}.${extension}`
if (Platform.OS === 'web') {
formData.append('filesToUpload', file, fileName)
} else {
formData.append('filesToUpload', {
uri: fileInfo.uri,
type: `image/${extension}`,
name: fileName,
})
}
//Other unrelated code
}
xhr.open('GET', url)
xhr.send()
Then the request:
const task = await fetch(
new Request(`${Constants?.manifest?.extra?.hostname}/ext/tasks`, {
method: 'POST',
}),
{
body: formData,
headers,
}
)
The headers just includes an authorisation token related to the user submitting the application.
So yeah, on web and iOS, this processes with no issue, but on Android, it starts the request, but never hits the endpoint.
Any help would be appreciated.
EDIT
I have been doing some debugging, and I think the issue is that the the file is not giving me a type from the blob, so in my formData type: 'image/${extension}', the extension does not exist.
So I logged the file object on both Android and iOS, and this is what I got.
iOS
{"_data": {"__collector": {}, "blobId": "1B56DE00-DDE9-494A-B57A-343040B6D12B", "name": "users_zw3GBtId4O0m0FAtpc94AUgBchPU_mutable_b293b904-6711-4384-a1c2-e540f5d6c1f8.png", "offset": 0, "size": 455495, "type": "image/png"}}
Android
{"_data": {"__collector": {}, "blobId": "11a2875e-903c-4f87-a997-7e31c7013cfb", "offset": 0, "size": 179757}}
So as yo can see, the iOS app is giving me more data, and also the extension of the file.
I still don't know why this is the case.
I am currently working on a simple app for scanning, reading data from an NFC card (in my case a Mifare NFC card) and displaying in on the screen. I have built it using this example.
The app should work both on Android and iOS, but for the moment, I have tested it only on an android device (an Oppo device with NFC capablities and developer mode activated).
At the launch of the app, everything seems to be working fine, the NfcManager has been successfully started, but there is an issue when the app tries to request the technology for reading the card, namely, I have to bring the app first in the background and then again in the foreground so that the message requestTechnology success is displayed, otherwise, it's simply not called.
After this, the promise NfcManager.getTag() gets rejected with the error message: no reference available.
Here is my code:
componentDidMount() {
NfcManager.start({
onSessionClosedIOS: () => {
alert('ios session closed');
},
}).then(() => console.warn('NfcManager started')) // successfully started
.catch((error) => alert('Error starting NfcManager: ', error));
}
{... componentWillUnmount and render method ...}
_read = async () => {
try {
let tech = Platform.OS === 'ios'
? NfcTech.MifareIOS : [NfcTech.MifareClassic, NfcTech.NfcA, NfcTech.IsoDep, NfcTech.Ndef];
let resp = await NfcManager.requestTechnology(tech, {
alertMessage: 'Ready to do some custom Mifare cmd!'
})
.then((value) => alert('requestTechnology success', value)) // here the value is empty, so no NfcTech
.catch(() => console.warn('reuqestTechnology error'));
const tag = await NfcManager.getTag()
.then((value) => alert('Tag event: ', value))
.catch((err) => console.warn('error getting tag: ', err));
// this part of the code is reached, but not working properly since the tag.id is not correctly retrieved
if (Platform.OS === 'ios') {
resp = await NfcManager.sendMifareCommandIOS([0x30, 0x00]);
} else {
resp = await NfcManager.transceive([0x30, 0x00]);
}
console.warn('Response: ', resp);
this._cleanUp();
} catch (ex) {
console.warn(ex);
this._cleanUp();
}
}
If I scan the card against the device, it makes the sound like it has been scanned, but nothing seems to be displayed.
Does anyone know why does the app needs to be brought to the background so that the technology is requested? And second, does the fail of the getTag() method have anything to do with it?
I hope anyone can help me with this issue, I have been struggling with this problem for quite some time and I haven't found any solution.
May be related to github.com/revtel/react-native-nfc-manager/issues/423 ?? there seems to be a scenario where this package does not correctly configure enableForegroundDispatch and manually pausing and resuming the App by sending it to the background would fix it.
I'm a native Android/iOS dev new to ionic capacitor and javascript in general. I'm trying to send data from Android's OnNewIntent callback to the ionic-react project I'm working on. I'm doing this in the native MainActivity.java that extends BridgeActivity:
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
getBridge().triggerDocumentJSEvent("MyEvent","blah");
}
And in my App.tsx file, I have something like this:
const App: React.FC = () => {
const onMyEvent = (input: string): void => {
console.log('event received: ${input}');
};
useEffect(() => {
document.addEventListener('MyEvent', () => {
console.log('MyEvent document');
onMyEvent(it.name);
});
window.addEventListener('MyEvent', () => {
console.log('MyEvent window');
onMyEvent(it.name);
});
}, []);
but I can't for the life of me get a message through from the native Activity to the App.tsx file. I've tried delaying the trigger for up to 15 seconds after the Activity is resumed to make sure everybody is instantiated, but I still never see indication that the message has been received. Is there an easy way to communicate from the native layer to the capacitor layer that I'm missing? Is it that these early Android lifecycle events happen before the ionic listeners have a chance to register? Just trying to send startup data that only the native side knows to the ionic side before rendering the first screen.
Thanks!
Scott
i used node js as a backend in a remote server(not localhost) with "188.226.146.190:3000/api/meetups", but i got network error in android 5.1 physical devise and return undefined as output of api,what should i do? i used a simple get requset to my api. i test an example api "https://jsonplaceholder.typicode.com/users" and it works properly with this test api.
i have an api file:
export const fetchMeetups = () =>
fetch('http://188.226.146.190:3000/api/meetups')
.then(res => res.json()).catch((e) =>e);
and in the app.js:
static defaultProps = {
fetchMeetups
}
state = {
loading: false,
meetups: []
}
async componentDidMount() {
this.setState({
loading: true
});
const data = await this.props.fetchMeetups();
setTimeout( () => this.setState({loading: false, meetups:
data.meetups}),2000);
}
and in the android i got this error:
Network request failed
Network request failed normally means the the server was not reachable.
To get more information about failures like this you can add Stetho to your project. It allows you to see failures in the network tab of your browsers and examine them like you would do in the tests.
The React Native docs have a detailed section about this at debugging#debugging-with-stetog.
In your case I would assume that the IP of your service is not up-to-date anymore, you might want to check this.
I'm using Ionic Framework to build an iOS / Android app which writes sqlite data to a CSV file, then attaches that file to an Email and sends it. The following code works correctly on iOS (actual device iPhone 5).
I don't have an Android device, but in the Android emulator (nexus 5), the file sent never has a file attachment (despite the emulator showing that it does).
Is there a different way I should be writing this code?
I looked at the documentation here, but it does not clarify
https://github.com/katzer/cordova-plugin-email-composer#adding-attachments
$cordovaFile.writeFile(cordova.file.dataDirectory,
"PatientEncounters.csv",
data.join("\n"),
true)
.then(function (success) {
$cordovaEmailComposer.isAvailable().then(function() {
var emailOpts = {
to: [email],
attachments: ['' +
cordova.file.dataDirectory.replace('file://','') + "PatientEncounters.csv"],
subject: 'Patient Encounters',
body: 'A CSV containing Patient Encounters is attached',
isHtml: false
};
$cordovaEmailComposer.open(emailOpts).then(null, function () {
// user cancelled email
});
return;
}, function (error) {
return;
});
}, function () {
// not available
});
My problem was using cordova.file.dataDirectory instead of cordova.file.externalDataDirectory. The mail app in android would not allow attaching files from internal storage.