I've been doing some research and android seems a bit stricter on waking up screen (light up device screen) when push notification is received.
What I would like to achieve is like a text message notification that it would turn on the screen, sound and vibrate. But my push notification only chime or vibrate. Is waking up the device from sleeping possible in cordova? I am using pubnub for the backend.
Here's my sample fcm payload:
var pushPayload = {
"message": "Some message",
"user_id": "1",
"pn_gcm" : {
"priority" : "high",
"data" : {
"title":"Notification title",
"body":"You are a winner!",
"room" : "Room name",
//"count" : 5,
"content-available":"1",
"force-start": "1",
"priority":2
}
}
};
And here's my piece of AndroidManifest.xml
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="27" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.VIBRATE" />
I am using phonegap-plugin-push.
Ok, I ended up creating my own cordova plugin just to handle on waking up screen. And here's the code that I used in my plugin:
Context context = this.cordova.getActivity().getApplicationContext();
PowerManager powerManager = (PowerManager) context.getSystemService(context.POWER_SERVICE);
boolean result= Build.VERSION.SDK_INT>= Build.VERSION_CODES.KITKAT_WATCH&&powerManager.isInteractive()|| Build.VERSION.SDK_INT< Build.VERSION_CODES.KITKAT_WATCH&&powerManager.isScreenOn();
if (!result){
PowerManager.WakeLock wl = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK |PowerManager.ACQUIRE_CAUSES_WAKEUP |PowerManager.ON_AFTER_RELEASE,"MH24_SCREENLOCK");
wl.acquire(10000);
PowerManager.WakeLock wl_cpu = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,"MH24_SCREENLOCK");
wl_cpu.acquire(10000);
}`
So, in the notification event, I called my plugin like this:
`
push.on('notification', function(data) {
//call wakeup screen
window.plugins.wakeUpScreen.wakeup(function() {
console.log('Wake up!');
}, function(err) {
console.log('Wake up error: ' + err);
});
}); `
Android devices have their own notification preferences and some cannot be overridden by your app. The "Ambient Display" setting will have the screen wake upon notification, but this is a feature that must be turned on in the phone settings.
Related
I want to make a screen page that can be navigated in the contact list on my phone. so I made a native module for get contact, It worked but for android 10 and below. For android 11 he can't run. The function I created can't get contact data.I've made sure all the permissions are there. Below is the code I made
const getChooseContact = () => {
const { ContactsWrapper } = NativeModules;
ContactsWrapper.getContact()
.then((contact) => {
setPhoneNumber(contact.phoneNumber);
})
.catch((error) => {
console.log(error);
});
};
const requestMediaPermission = async () => {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.READ_CONTACTS,
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
getChooseContact();
} else {
setErrorMessage('Access media permission denied');
}
} catch (err) {
console.log(err);
}
};
This is majorly because in API 30 and above we can no-longer interact with external modules without specifically being allowed the interaction.
This can happen in two ways one using the <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" /> inside the androidmanifest.xml though this is discouraged since it can have your app rejected Read this kindly https://support.google.com/googleplay/android-developer/answer/10158779#zippy=%2Cpermitted-uses-of-the-query-all-packages-permission
to fix your issue
inside build.gradle under android update class paths to this :
classpath 'com.android.tools.build:gradle:3.5.4' this allows for the next step to be recognised during bundling otherwise your will get an error
inside androidmanifest.xml before the application tag add this
<queries>
<!-- Browser -->
<intent android:label="View Contact">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="vnd.android.cursor.item/person" android:host="contacts" />
</intent>
</queries>
I added admob interstitial to my android app.
The app and interstitial are working fine on emulator, with TestID and a real ID. But on real devices it is not showing any ad, and there is no crashes or errors.
Could you please help me to find what might be the reason? Here is my code :
import admob, { InterstitialAd, TestIds, AdEventType } from '#react-native-firebase/admob';
...
showAdss(){
const idx = 'ca-app-pub-3....10';
const interstitial = InterstitialAd.createForAdRequest(idx, {
requestNonPersonalizedAdsOnly: true,
keywords: ['fashion', 'clothing']
});
interstitial.onAdEvent((type) => {
if (type === AdEventType.LOADED) {
interstitial.show();
}
});
and from manifest file :
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
...
Quickly my environment :
Phonegap 8.0.0
phonegap-plugin-push 2.1.2 (the last version is not compatible to phonegap 8.0.0)
At that time :
I manage to receive push notification generated from my local machine via "phonegap push " in the phonegap simulator
I can’t receive push notif from Firebase in the phonegap simulator (is it possible ?)
When I build the app for Android, she crash at start (blank page) due to the phonegap-plugin-push associated code in my app (if I comment it, she start normally)
My code (VueJS framework)
console.log('calling push init');
window.gtvapp.push = PushNotification.init({
'android': {
// 'senderID': 'XXXXXXXX'
},
'browser': {},
'ios': {
'sound': true,
'vibration': true,
'badge': true,
'alert': true
// 'senderID': 'xxxxxxxx'
},
'windows': {}
})
console.log('after init')
window.gtvapp.push.on('registration', function(data) {
console.log('registration event: ' + data.registrationId)
var oldRegId = window.localStorage.getItem('registrationId')
if (oldRegId !== data.registrationId) {
window.localStorage.setItem('registrationId', data.registrationId)
// Post registrationId to your app server as the value has changed
// TODO
}
})
window.gtvapp.push.on('error', function(e) {
console.log('push error = ' + e.message)
})
// (...)
let router = this.$router
window.gtvapp.push.on('notification', function(data) {
console.log('notification event')
console.log(JSON.stringify(data))
if (device.platform === 'Android') {
navigator.notification.alert(
data.message, // message
function() {
console.log(window.location.pathname)
console.log(data.additionalData.path)
// window.localStorage.setItem('pushpath', data.additionalData.path)
router.push(data.additionalData.path)
},
data.title,
'En savoir plus'
)
}
})
This code works perfectly as attended on simulator "phonegap serve" + local push notif "phonegap push "
Questions :
step 1 : is it theoricaly possible to receive Firebase notif in a "phonegap serve instance"
step 2 : is just "google-services.json" file required to correctly configure the firebase registration
Thanks a lot
step 1 : is it theoricaly possible to receive Firebase notif in a "phonegap serve instance"
No it’s not, you have to build the app and install the apk on the device
step 2 : is just "google-services.json" file required to correctly configure the firebase registration
Yes.
Just on thing for phonegap 8 :
<platform name="android">
<resource-file src="google-services.json" target="app/google-services.json" />
</platform>
the "app/" is important.
We use FileOpener2 plugin for cordova to open a downloaded .apk file from our servers. Recently, we found that Android 6.0 or higher devices are throwing an exception only on the file open process. We were able to trace this down to the cordova.js file, where the posted exception occurs. We have yet to find a cause or a fix, but have put a workaround in place. Any info would be amazing on this so we can maintain our in-app self updating process going on all Android devices.
Code (Working on Android <= 6.0):
// we need to access LocalFileSystem
window.requestFileSystem(LocalFileSystem.PERSISTENT, 5 * 1024 * 1024, function (fs) {
//Show user that download is occurring
$("#toast").dxToast({
message: "Downloading please wait..",
type: "warning",
visible: true,
displayTime: 20000
});
// we will save file in .. Download/OURAPPNAME.apk
var filePath = cordova.file.externalRootDirectory + '/Download/' + "OURAPPNAME.apk";
var fileTransfer = new FileTransfer();
var uri = encodeURI(appDownloadURL);
fileTransfer.download(uri, filePath, function (entry) {
//Show user that download is occurring/show user install is about to happen
$("#toast").dxToast({
message: "Download complete! Launching...",
type: "success",
visible: true,
displayTime: 2000
});
////Use pwlin's fileOpener2 plugin to let the system open the .apk
cordova.plugins.fileOpener2.open(
entry.toURL(),
'application/vnd.android.package-archive',
{
error: function (e) {
window.open(appDownloadURL, "_system");
},
success: function () { console.log('file opened successfully'); }
}
);
},
function (error) {
//Show user that download had an error
$("#toast").dxToast({
message: error.message,
type: "error",
displayTime: 5000
});
},
false);
})
Debugging Information:
THIS IS NOT OUR CODE, BUT APACHE/CORDOVA CODE
Problem File: cordova.js
function androidExec(success, fail, service, action, args) {
// argsJson - "["file:///storage/emulated/0/download/OURAPPNAME.apk","application/vnd.android.package-archive"]"
//callbackId - FileOpener21362683899
//action - open
//service FileOpener2
//bridgesecret - 1334209170
// msgs = "230 F09 FileOpener21362683899 sAttempt to invoke virtual method 'android.content.res.XmlResourceParser //android.content.pm.PackageItemInfo.loadXmlMetaData(android.content.pm.PackageManager, java.lang.String)' on a null object reference"
var msgs = nativeApiProvider.get().exec(bridgeSecret, service, action, callbackId, argsJson);
// If argsJson was received by Java as null, try again with the PROMPT bridge mode.
// This happens in rare circumstances, such as when certain Unicode characters are passed over the bridge on a Galaxy S2. See CB-2666.
if (jsToNativeBridgeMode == jsToNativeModes.JS_OBJECT && msgs === "#Null arguments.") {
androidExec.setJsToNativeBridgeMode(jsToNativeModes.PROMPT);
androidExec(success, fail, service, action, args);
androidExec.setJsToNativeBridgeMode(jsToNativeModes.JS_OBJECT);
} else if (msgs) {
messagesFromNative.push(msgs);
// Always process async to avoid exceptions messing up stack.
nextTick(processMessages);
}
So I have seen other people with this issue post on here. Nothing seems to right with what I am having. Here is the steps of my issues:
1) I installed my Ionic app onto my phone.
2) Setup my sender key and API key with the google console.
3) Created my node-gcm server.
4) Sent notifications to my phone using my phonegap-plugin-push device token.
5) uninstalled my app
6) reinstalled the app.
7) tried sending notifications, and now I am getting a NotRegistered Error by GCM.
I cross checked all of my keys: server, sender, device. All are correct. I cannot figure out why after reinstallation of the app, i get a notregistered error. Here are the tools I am using:
Ionic framework, android phone, NodeJS server, Node-gcm, google dev console, phonegap-plugin-push
And lastly, Code:
.run(function($ionicPlatform, $ionicPopup, $rootScope, $http, $state) {
$ionicPlatform.ready(function() {
var push = PushNotification.init({
android: {
senderID: "7821....1490",
sound: "true",
vibration: "true"
},
browser: {
pushServiceURL: 'http://push.api.phonegap.com/v1/push'
},
ios: {
alert: "true",
badge: true,
sound: "true",
vibration: "true",
clearBadge: true
},
windows: {}
});
push.on('registration', function(data) {
console.log("Device Token: " + data.registrationId);
$rootScope.devToken = data.registrationId;
})
var message = new gcm.Message();
message.addData('title', 'Alert');
message.addData('message', 'Message From: '+ messageUser + '\n' + 'Message Text: ' + messageText);
//message.addData('image', image);
sender.send(message, android, function (err, response) {
if(err) {}
else {
console.log(response.results);
//response is NotRegistered, unregister devices
for (var i = 0; i < response.results.length; i++) {
if (response.results[i].error == 'NotRegistered') {
console.log("ERROR");
}
}
}
});
I am willing to work through this with you. Just know, I have checked all keys, and all are the correct keys. When I reinstalled the app, I got a new device token and I am trying to push to that new device token.
OK! FOR ANYONE WITH THIS PROBLEM READ HERE!
With push plugin, on app uninstall. It does not clear all the data. I am storing the device token in a scope variable and storing it in local storage. On app uninstall, go to settings and clear all data before uninstalling. Once you reinstall, you will get a new token and it should work!