I'd like to implement push notifications in android ?
I prefer not to use an existing plugins
would someone give me an example of code on how to send a message
have been struggling since a week none of my tries have been successfull
This is my last try:
gcm.py
import requests
import json
def send_gcm_message(api_key, regs_id, data, collapse_key=None):
"""
Send a GCM message for one or more devices, using json data
api_key: The API_KEY from your console (https://code.google.com/apis/console, locate Key for Server Apps in
Google Cloud Messaging for Android)
regs_id: A list with the devices which will be receiving a message
data: The dict data which will be send
collapse_key: A string to group messages, look at the documentation about it:
http://developer.android.com/google/gcm/gcm.html#request
"""
values = {
'registration_ids': regs_id,
'collapse_key': collapse_key,
'data': data
}
values = json.dumps(values)
headers = {
'UserAgent': "GCM-Server",
'Content-Type': 'application/json',
'Authorization': 'key=' + api_key,
}
response = requests.post(url="https://android.googleapis.com/gcm/send",
data=values,
headers=headers)
return response.content
views.py
import settings
from .gcm import send_gcm_message
#render_to("push/envoyer_message.html")
def send_message(request):
if not request.user.is_authenticated():
return HttpResponseRedirect('/client/login')
else:
if request.method == 'POST':
form = MessageForm(request.POST)
if form.is_valid():
form.save()
reg_id='APA91bFSIEHPOeT2I7ddCqnYtnJ-iAEQfCiR3HArUIz0t5lQUVfIOGhlEIUJCJLY7SWEdwiJCHedLNaSFi6oVqbnsci9-HmpBNiZAa86KD3349AIWMesweUqF2YbfpSBRot1tNLCITRFbYH9g5AO514s8Zzs4ABumA'
msg='test'
send = send_gcm_message(api_key = settings.GCM_APIKEY, regs_id=[reg_id], data={'msg': msg},collapse_key="message")
messages.success(request, _(u'Formulaire envoyé avec succès.'))
return HttpResponseRedirect(reverse("push-confirmation-envoi"))
else:
form = MessageForm()
return locals()
EDIT:
This is the error I get :
Field "data" must be a JSON array: test www
SOLVED
regs_id = list()
for device in devices_a :
regs_id.append(device.token_string)
message = json.dumps(message)
values = {
'registration_ids': regs_id,
'collapse_key': "message" ,
'data': {"message":str(msg.message)}
}
headers = {
'UserAgent': "GCM-Server",
'Content-Type': 'application/json',
'Authorization': 'key=' + settings.GCM_APIKEY,
}
response = requests.post(url="https://android.googleapis.com/gcm/send",data=json.dumps(values), headers=headers)
r = json.loads(response.content)
msg.nbr_android_recieved = r["success"]
Related
According to node.js Documentation encoding : null when binary data to be sent via Api,
https://www.npmjs.com/package/request in this link below mentioned explanation is found.
encoding - encoding to be used on setEncoding of response data. If
null, the body is returned as a Buffer. Anything else (including the
default value of undefined) will be passed as the encoding parameter
to toString() (meaning this is effectively utf8 by default).
Note: if you expect binary data, you should set encoding: null.
Now I have achieve the same thing in flutter/dart and this encoding parameter is not accepting null as here in node.js they have mentioned.
I want to know how to make this same Post request from Flutter/dart or at least android/java.
var enc = AESCrypt.encrypt(key, iv, JSON.stringify(obj_j));
var output = new Buffer.from(enc, 'hex'); // Buffer
function test() {
console.time("XXX");
request.post({
headers: {
'content-type': 'application/json'
}, //required, or webserver will ignore it application/json multipart/form-data
url: 'http://192.168.29.210/deviceid/read', // webserver url
encoding:null,
body: output
},
function (error, response, body) {
if (!error && response.statusCode == 200) {
console.timeEnd("XXX");
body = AESCrypt.decrypt(key, iv, body);
//body is decrypted http response, can be parsed with json method
fs.writeFile('input.json', body, function (err) {
if (err) {
return console.error(err);
}
});
}
});
};
Adding code the What i have tried in flutter
var headers = {'Content-Type': 'application/json'};
var request =
http.Request('POST', Uri.parse('http://192.168.29.210/deviceid/read'));
request.body = encryptedText;
request.encoding = null ; // here this null parameter is not acceptable
request.encoding = Encoding.getByName("utf-8")); // only this option is available to add in flutter
request.headers.addAll(headers);
http.StreamedResponse response = await request.send();
Even in post man this encoding variable is not present to set it.
Use below flutter framework method
Future<Response> post(Uri url,
{Map<String, String>? headers, Object? body, Encoding? encoding}) =>
_withClient((client) =>
client.post(url, headers: headers, body: body, encoding: encoding));
How to use
final url = Uri.parse('$urlPrefix/posts');
final headers = {"Content-type": "application/json"};
final json = '{"title": "Hello", "body": "body text", "userId": 1}';
final response = await post(url, headers: headers, body: json,encoding:null); //here this null parameter is not acceptable
My Final working code is
var headers = {'Content-Type': 'application/json'};
final response = await http.post(
Uri.parse('http://192.168.29.210/deviceid/read'),
headers: headers,
body: encryptedText,
encoding: null);
if (response.statusCode == 200) {
String res = response.body.toString();
//String data = AesEncryption().decryption(res);
print('Body: ${response.body.toString()}');
} else {
print(response.reasonPhrase);
}
print('Status code: ${response.statusCode}');
Sending push notifications from device to device works fine with this code, but only on Android and from a browser.
For some reason this does not work on iOS, no matter if I use the postData object or the stringified payload. Any ideas why?
import { HttpClient } from '#angular/common/http';
public sendPushNotificationToToken(token: string, pnServerKey: string, message: string, userId: number): Observable<any> {
const firebaseUrl = "https://fcm.googleapis.com/fcm/send";
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': 'key=' + pnServerKey
})
};
const postData = {
'to': token,
'priority':'normal',
'notification': {
'title': message,
'message': message,
'userId': userId
},
};
return this.http.post(firebaseUrl, postData, httpOptions);
The only way to solve this was to use "#ionic-native/http/ngx" instead of '#angular/common/http'. Still don't see why the google Server refused to accept my payload.
this is the code.
Future<http.Response> postRequest () async {
var url ='http://10.0.2.2:3000/api/message';
Map data = {
'message': '12345678901234567890'
};
//encode Map to JSON
var body = json.encode(data);
var response = await http.post(url,
headers: { "accept": "application/json", "content-type": "application/json" },
body: body
);
print("${response.statusCode}");
print("${response.body}");
return response;
}
postRequest();
// also tried this: headers: {"content-type":"application/json" },
In my python flask server, the post message is logging, but with empty body into it.
The flutter app is running on Android Virtual Device and the server is still running on http://0:0:0:0:3000/ and it's using request.get_json() in the method.
Using postman, everything works as expected on my server so I see the problem in the app.
postman details:
POST: http://localhost:3000/api/message
headers
KEY | VALUE
Content-Type | application/json
Body raw
{
"message": "opa"
}
also raised here: https://github.com/flutter/flutter/issues/39351
Try passing :
Future<http.Response> postRequest () async {
var url ='http://10.0.2.2:3000/api/message';
Map<String, String> data = { "message": "opa" };
var body = json.encode(data);
var response = await http.post(url,
headers: { "accept": "application/json", "content-type": "application/json" },
body: body
);
print(response.statusCode);
print(response.body);
return response;
}
postRequest().then((response){
print(response.body);
});
not sure if my finding is precious or not for community, but it seems that the URL was the problem. Everything works now, but I added a / in the end of the string in my flask app.
In Postman, I didn't have to do this. So if you have same problem, take care :)
The log from Flask server:
127.0.0.1 - - [30/Aug/2019 17:41:32] "POST /api/message/ HTTP/1.1" 200 -
opa
My Flask url is:
#app.route('/api/message/', methods=['POST'])
def function():
I have already push the GCM message to google server using asp .net in following method,
GCM Push Notification with Asp.Net
Now i have planned upgrade to FCM method, anyone have idea about this or developing this in asp .net let me know..
2019 Update
There's a new .NET Admin SDK that allows you to send notifications from your server.
Install via Nuget
Install-Package FirebaseAdmin
You'll then have to obtain the service account key by downloading it by following the instructions given here, and then reference it in your project. I've been able to send messages by initializing the client like this
using FirebaseAdmin;
using FirebaseAdmin.Messaging;
using Google.Apis.Auth.OAuth2;
...
public class MobileMessagingClient : IMobileMessagingClient
{
private readonly FirebaseMessaging messaging;
public MobileMessagingClient()
{
var app = FirebaseApp.Create(new AppOptions() { Credential = GoogleCredential.FromFile("serviceAccountKey.json").CreateScoped("https://www.googleapis.com/auth/firebase.messaging")});
messaging = FirebaseMessaging.GetMessaging(app);
}
//...
}
After initializing the app you are now able to create notifications and data messages and send them to the devices you'd like.
private Message CreateNotification(string title, string notificationBody, string token)
{
return new Message()
{
Token = token,
Notification = new Notification()
{
Body = notificationBody,
Title = title
}
};
}
public async Task SendNotification(string token, string title, string body)
{
var result = await messaging.SendAsync(CreateNotification(title, body, token));
//do something with result
}
..... in your service collection you can then add it...
services.AddSingleton<IMobileMessagingClient, MobileMessagingClient >();
C# Server Side Code For Firebase Cloud Messaging
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;
using System.Web.Script.Serialization;
namespace Sch_WCFApplication
{
public class PushNotification
{
public PushNotification(Plobj obj)
{
try
{
var applicationID = "AIza---------4GcVJj4dI";
var senderId = "57-------55";
string deviceId = "euxqdp------ioIdL87abVL";
WebRequest tRequest = WebRequest.Create("https://fcm.googleapis.com/fcm/send");
tRequest.Method = "post";
tRequest.ContentType = "application/json";
var data = new
{
to = deviceId,
notification = new
{
body = obj.Message,
title = obj.TagMsg,
icon = "myicon"
}
};
var serializer = new JavaScriptSerializer();
var json = serializer.Serialize(data);
Byte[] byteArray = Encoding.UTF8.GetBytes(json);
tRequest.Headers.Add(string.Format("Authorization: key={0}", applicationID));
tRequest.Headers.Add(string.Format("Sender: id={0}", senderId));
tRequest.ContentLength = byteArray.Length;
using (Stream dataStream = tRequest.GetRequestStream())
{
dataStream.Write(byteArray, 0, byteArray.Length);
using (WebResponse tResponse = tRequest.GetResponse())
{
using (Stream dataStreamResponse = tResponse.GetResponseStream())
{
using (StreamReader tReader = new StreamReader(dataStreamResponse))
{
String sResponseFromServer = tReader.ReadToEnd();
string str = sResponseFromServer;
}
}
}
}
}
catch (Exception ex)
{
string str = ex.Message;
}
}
}
}
APIKey and senderId , You get is here---------as follow(Below Images)
(go to your firebase App)
public class Notification
{
private string serverKey = "kkkkk";
private string senderId = "iiddddd";
private string webAddr = "https://fcm.googleapis.com/fcm/send";
public string SendNotification(string DeviceToken, string title ,string msg )
{
var result = "-1";
var httpWebRequest = (HttpWebRequest)WebRequest.Create(webAddr);
httpWebRequest.ContentType = "application/json";
httpWebRequest.Headers.Add(string.Format("Authorization: key={0}", serverKey));
httpWebRequest.Headers.Add(string.Format("Sender: id={0}", senderId));
httpWebRequest.Method = "POST";
var payload = new
{
to = DeviceToken,
priority = "high",
content_available = true,
notification = new
{
body = msg,
title = title
},
};
var serializer = new JavaScriptSerializer();
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string json = serializer.Serialize(payload);
streamWriter.Write(json);
streamWriter.Flush();
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
result = streamReader.ReadToEnd();
}
return result;
}
}
To hit Firebase API we need some information from Firebase, we need the API URL (https://fcm.googleapis.com/fcm/send) and unique keys that identify our Firebase project for security reasons.
We can use this method to send notifications from .NET Core backend:
public async Task<bool> SendNotificationAsync(string token, string title, string body)
{
using (var client = new HttpClient())
{
var firebaseOptionsServerId = _firebaseOptions.ServerApiKey;
var firebaseOptionsSenderId = _firebaseOptions.SenderId;
client.BaseAddress = new Uri("https://fcm.googleapis.com");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization",
$"key={firebaseOptionsServerId}");
client.DefaultRequestHeaders.TryAddWithoutValidation("Sender", $"id={firebaseOptionsSenderId}");
var data = new
{
to = token,
notification = new
{
body = body,
title = title,
},
priority = "high"
};
var json = JsonConvert.SerializeObject(data);
var httpContent = new StringContent(json, Encoding.UTF8, "application/json");
var result = await _client.PostAsync("/fcm/send", httpContent);
return result.StatusCode.Equals(HttpStatusCode.OK);
}
}
These parameters are:
token: string represents a FCM token provided by Firebase on each app-installation. This is going to be the list of app-installations that the notification is going to send.
title: It’s the bold section of notification.
body: It represents “Message text” field of the Firebase SDK, this is the message you want to send to the users.
To find your Sender ID and API key you have to:
Login to the Firebase Developer Console and go to your Dashboard
Click on the “gear” icon and access “project settings”
Go to the
“Cloud Messaging Section” and you will have access to the sender ID
and the API Key.
Here is my VbScript sample for who prefers vb:
//Create Json body
posturl="https://fcm.googleapis.com/fcm/send"
body=body & "{ ""notification"": {"
body=body & """title"": ""Your Title"","
body=body & """text"": ""Your Text"","
body=body & "},"
body=body & """to"" : ""target Token""}"
//Set Headers :Content Type and server key
set xmlhttp = server.Createobject("MSXML2.ServerXMLHTTP")
xmlhttp.Open "POST",posturl,false
xmlhttp.setRequestHeader "Content-Type", "application/json"
xmlhttp.setRequestHeader "Authorization", "Your Server key"
xmlhttp.send body
result= xmlhttp.responseText
//response.write result to check Firebase response
Set xmlhttp = nothing
2020/11/28
download this file from Firebase -> Settings -> Service accounts -> Firebase Admin SDK
Move the downloaded file to Your dotnet Core Root folder then change it's name to key.json for example .
then add this code to your .csproj file: YourProjectName.csproj in your project root folder :
<ItemGroup>
<None Update="key.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
then add this code to your Program.cs in Main function :
var defaultApp = FirebaseApp.Create(new AppOptions()
{
Credential =
GoogleCredential.FromFile(Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
"key.json")),
});
Last thing is the code that will push notification :
public async Task SendNotificationAsync(string DeviceToken, string title ,string body){
var message = new Message()
{
Notification = new FirebaseAdmin.Messaging.Notification
{
Title = title,
Body = body
},
Token = DeviceToken,
};
var messaging = FirebaseMessaging.DefaultInstance;
var result = await messaging.SendAsync(message);
}
Put it in any Controller then u can call it to send notification ...
that is what i did to push notificaion and it is working very well and fast ...
Use CorePush lib
It's very lightweight. I use it across all my projects to send Firebase Android, WebPush and Apple iOS push notifications. Useful links:
NuGet package
Documentation
The interface is very simple and minimalistic:
Send APN message:
var apn = new ApnSender(settings, httpClient);
await apn.SendAsync(notification, deviceToken);
Send FCM message:
var fcm = new FcmSender(settings, httpClient);
await fcm.SendAsync(deviceToken, notification);
I don't believe there is any change in the way you are sending push notifications. In FCM also, you are going to make HTTP POST Request the same way you did for GCM:
https://fcm.googleapis.com/fcm/send
Content-Type:application/json
Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA
{ "data": {
"score": "5x1",
"time": "15:10"
},
"to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1..."
}
Read about FCM Server for more information.
The only change I could see now, is the target Url. Period.
push: function (tokens, message) {
var privateKey = 'xxx';
var appId = 'xxx';
var auth = btoa(privateKey + ':');
var req = {
method: 'POST',
url: 'https://push.ionic.io/api/v1/push',
headers: {
'Content-Type': 'application/json',
'X-Ionic-Application-Id': appId,
'Authorization': 'basic ' + auth
},
data: {
"tokens": tokens,
"notification": {
"alert": message
}
}
};
// Make the API call
$http(req).success(function (resp) {
// Handle success
console.log(tokens);
console.log(resp);
}).error(function (error) {
// Handle error
console.log("Ionic Push: Push error...");
});
}
I am using the above code to push notifications. It gets into the
success handler and prints the token used and message id, to the console. But when i check the status with the message id, its saying Push Error Code 101.
When i use the same token using Ionic.io website for one time notification screen, it works !
How can i make this working using angular code ?
Thanks !