grails app, using java-apns - java

I have a grails app, and I am using the java-apns 0.1.5 jar! I have a device key, which already uninstall my app from it, so my question is, should I receive same feedback from the API saying that device is not enable anymore?
My code is the following:
apnsService = APNS.newService()
.withCert(pathToCertificate, password)
.withFeedbackDestination("feedback.sandbox.push.apple.com",2196)
.withSandboxDestination()
.build();
apnsService.start();
Map<String, Date> inactiveDevices = apnsService.getInactiveDevices();
log.debug inactiveDevices
.....
the think is that, the variable inactiveDevices is always empty! why? if I uninstall the app from the device?! am I missing some think in the client(device) side?

If you are using the Sandbox destination, the feedback service may not
report info correctly. This is a known bug with a known workaround,
check the mailing list thread
The problem comes from the "Sandbox" APNs Feedback server, probably a
bug. Here is the solution if anyone has the same problem:
Create a dummy app id in the program portal, enable development push
notifications on it Create and download the associated provisioning
profile Create a new xcode project, and invoke the
registerForRemoteNotificationTypes method on start. Install the dummy
app on your device. At this point, you should have two DEVELOPMENT
apps running on your device: the original app and the dummy app. Both
should be registered to receive push notifications. Uninstall the
original app, and try to send a push notification to that app. Invoke
the feedback service, and you should receive data back.
To resume, the Sandbox Feedbacks server needs TWO DEVELOPMENT Apps
registered on the SAME iPhone to work. This manipulation is not
necessary for the production phase as the "Production" APNs Feedback
server works fine.
I would recommend just switching to test feedback with the production servers.
Please either test with the production servers or use the workaround.

Hello Guys i have done push using grails APNS also with simple java lib.
1. With Grails : here is code snippet for APNS using grails
Hello Guys i have done push using grails APNS.
there are one Important point to remember
1. Proper apple certificate, Apple approved.: Apple approve certificate after 24 hours.
here is my code
1. in config.groovy
environments {
development {
apns {
pathToCertificate = "/Users/sarbogast/Desktop/APNs_development_certificates.p12"
password = "password"
environment = "sandbox"
}
} test {
apns {
pathToCertificate = "/usr/local/myapp/APNs_development_certificates.p12"
password = "password"
environment = "sandbox"
}
} production {
apns {
pathToCertificate = "/usr/local/myapp/APNs_production_certificates.p12"
password = "password"
environment = "production"
}
}
}2. i create a service and here is my service class code def sendMessageToDevices() { List<string> aa = new ArrayList<string>() aa.add("Testing") def payload = APNS.newPayload() .badge(1) .localizedKey("key") .localizedArguments(aa) .sound("default") log.error(payload.length()) if (payload.isTooLong()){ log.info("Message is too long: " + payload.length()) } try { apnsService.testConnection() apnsService.push("Device token here", payload.build() ) } catch (Exception e) { log.error("Could not connect to APNs to send the notification"+e.getMessage()) } }
here "key" is any message which will popup on device push
3. i called this method by controller method..

Related

How to fix AWS 403 error "Check your AWS Secret Access Key and signing method" when calling SES listcontacts

I have been stuck for about the past 6 hours at this point I'm thinking the only reasonable explanations are that this is a AWS SDK bug or the error message is wrong.
I am using SESv2 class from the AWS SDK in a JAVA SpringBoot app and attempting to manage various details of my SES (Simple Email Service) account.
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sesv2.SesV2Client;
import software.amazon.awssdk.services.sesv2.model.*;
I have created an IAM user, created security credentials, set them up using multiple different methods as described here guid to credentials environment I've given full access to SES to this IAM role user. I then wrote some code and I was able to do all of the following,
Create a contact list
Delete a contact list
Create contact
Create a Topic in a contact list
Send an email
However, for some unknown reason when I go to test a function I wrote to get a list of contacts so I can test sending an email to multiple contacts I get the following 403 error message,
The request signature we calculated does not match the signature you
provided. Check your AWS Secret Access Key and signing method. Consult
the service documentation for details.
I've verified the credentials are correct. I have created a new set of credentials and made the old set inactive. No dice, all the functions listed above still work however the listContacts in the SesV2Client class still fails with the same error. As you can see below I even bypassed the env variables and just hardcoded the key and secret to pull out all the stops, still fails. In the function that fails, I've gone over and over the values im passing in they are valid and exist 100% because as I said I can make the other calls in the list above to verify the topics and contact list exists.
private List<Contact> listContactsForSiteUpdatesMailingList() {
try (SesV2Client client = SesV2Client.builder()
.region(Region.US_EAST_1)
.credentialsProvider(StaticCredentialsProvider.create(awsCreds))
.build()){
TopicFilter topicFilter = TopicFilter.builder().topicName(TOPIC_SITE_UPDATES).useDefaultIfPreferenceUnavailable(true).build();
ListContactsFilter listContactsFilter = ListContactsFilter.builder().topicFilter(topicFilter).filteredStatus(SubscriptionStatus.OPT_IN).build();
ListContactsRequest listContactsRequest = ListContactsRequest.builder()
.contactListName(CONTACT_LIST).filter(listContactsFilter).build();
ListContactsResponse listContactsResponse = client.listContacts(listContactsRequest);
return listContactsResponse.contacts();
} catch (Exception ex) {
System.out.println("The email was not sent. Error message: "
+ ex.getMessage());
return null;
}
}
Whats going on here and how can I get to the bottom of this error?
EDIT:
Looking at AWS Console Users>Access Management and then looking at the user a created I can even verify that there was "programmatic access"
An example of accessing a ContactList with no issues
EDIT 2: My SES account is currently sandboxed. I just wanted to mention the question is this possibly happening because of that? Grasping at straws here.
I was able to reproduce your issue. I created a list and added a contact. Both worked. However, when i executed listContacts, I got this error:
This looks like a bug. To address this, open a Github issue on the SDK Java Github here:
https://github.com/aws/aws-sdk-java
This is confirmed as a bug in the AWS SDK. To get around this you can use the async client like so
SesV2AsyncClient client = SesV2AsyncClient.builder()
.region(Region.US_EAST_1)
.build())
TopicFilter topicFilter = TopicFilter.builder().topicName(TOPIC_SITE_UPDATES).useDefaultIfPreferenceUnavailable(true).build();
ListContactsFilter listContactsFilter = ListContactsFilter.builder().topicFilter(topicFilter).filteredStatus(SubscriptionStatus.OPT_IN).build();
ListContactsRequest listContactsRequest = ListContactsRequest.builder()
.contactListName(CONTACT_LIST).filter(listContactsFilter).build();
CompletableFuture<ListContactsResponse> listContactsResponseCompletableFuture = client.listContacts(listContactsRequest);
ListContactsResponse listContactsResponse = listContactsResponseCompletableFuture.get();

not receiving push notification from firebase But with Pusher app

i do not get any notification from firebase but when i test with Pusher app i get the notification.
these are my steps i have Done. help me if i have done something wrong.
1_ add notificationService as below.
class NotificationService: UNNotificationServiceExtension {
var contentHandler: ((UNNotificationContent) -> Void)?
var bestAttemptContent: UNMutableNotificationContent?
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: #escaping (UNNotificationContent) -> Void) {
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
if let bestAttemptContent = bestAttemptContent {
// Modify the notification content here...
bestAttemptContent.title = "hello"
bestAttemptContent.body = "this is test"
contentHandler(bestAttemptContent)
}
}
}
2 _ set notificationCenter delegate to self in app delegate
Messaging.messaging().delegate=self
UNUserNotificationCenter.current().delegate = self
3_ device token for sending notification (i store this to server)
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
print("Firebase registration token: \(fcmToken)")
let dataDict:[String: String] = ["token": fcmToken]
NotificationCenter.default.post(name: Notification.Name("FCMToken"), object: nil, userInfo: dataDict)
// TODO: If necessary send token to application server.
// Note: This callback is fired at each app startup and whenever a new token is generated.
}
i send this FCMToken to server Side(java,spring boot)
4_ i have enabled push notification in Capabilities
5_ i have added .p12 file in cloud messaging of project settings in firebase console but i have big question for this !???? should i login to firebase with my server's account ? or make an account for my self ?? because i have created one for my self.
some tips :
we are a team like server side(JAVA). web , android and ios
which this push notification is working on android but not on ios.
i think i'm doing something in a wrong way.
thank you for reading this topic and helping me out.
Here is the steps to cross check your issue,
Notification Capabilities has to be enabled.
Certificate you created on apple member center should enable the push
notification
In firebase console go to settings -> project settings -> cloud messaging -> check the server key
This key and the key what you gave to you server team should be same
Check APNs Authentication Key or APNs Certificates added or not.
If you are using APNs Certificates, that should be same that you generated in the appId in the member center
get the fcm token from the xcode console -> go to firebase console -> grow -> cloud messaging -> new notification
-> and try test on device. if you receive notification client side (device) has no issues. if not server side has to double check the server key.
Add your googleServiceInfo.plist to your project. add the reversed key in your app info.
in Appdelegate, configure your firebase
FirebaseApp.configure()
Update, As per your question in the comment, am updating this question.
To make use of NotificationService Extension, you notification must include mutable-content property in the notification payload. using fcm api you can do that. put these in the post man,
https://fcm.googleapis.com/fcm/send
in the headers, add your server key (you can get this from your firebase console)
in the body add this payload to fire notification. this will trigger your Notification Service Extension.
{
"notification": {
"title": "1",
"body": "",
"click_action": "",
"icon": "",
"mutable_content": true,
"content_available": true
},
"registration_ids":["add your fcm token"],
"data": {}
}
As per the tutorial:
https://code.tutsplus.com/tutorials/ios-10-notification-service-extensions--cms-27550

GAE HttpResponseException: 401

I am trying to access the DataStore of one app from another GAE project using Remote API.
I am using the following code:
String serverString = "http://example.com";//this should be the target appengine
RemoteApiOptions options;
if (serverString.equals("localhost")) {
options = new RemoteApiOptions().server(serverString, 8080).useDevelopmentServerCredential();
} else {
options = new RemoteApiOptions().server(serverString, 80).useApplicationDefaultCredential();
}
RemoteApiInstaller installer = new RemoteApiInstaller();
installer.install(options);
datastore = DatastoreServiceFactory.getDatastoreService();
try {
results = datastore.get(KeyFactory.createKey("some key"));
} catch (EntityNotFoundException e) {
e.printStackTrace();
return null;
}
when I run this locally, i get a nullpointerexception at installer.install(options);.
and when deployed, the error seen from error reporting on the appengine is :HttpResponseException: 401 You must be logged in as an administrator, or access from an approved application.
That being said, I made a small java application with the follwing code:
String serverString = "http://example.com";//same string as the one used in the above code
RemoteApiOptions options;
if (serverString.equals("localhost")) {
options = new RemoteApiOptions().server(serverString, 8080).useDevelopmentServerCredential();
} else {
options = new RemoteApiOptions().server(serverString, 80).useApplicationDefaultCredential();
}
RemoteApiInstaller installer = new RemoteApiInstaller();
installer.install(options);
try {
DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
System.out.println("Key of new entity is " + ds.put(new Entity("Hello Remote API!")));
and this one works!! Hello Remote API entity is added.
The reason it does not work when running on App Engine vs running locally has to do with the credentials that are being picked up. When running locally, it is likely using your own credentials (which has access to both projects); by contrast, when running on App Engine, you are likely picking up the App Engine default service account, which only has access to that App Engine project.
Try fixing this by opening the Cloud IAM section of Cloud Console for the project containing the Cloud Datastore that you wish to access. There, grant the appropriate level of access to the default App Engine service account that is being used by the other project.
If you don't want all App Engine services in the other project to have this kind of access, you might also consider, instead, generating a service account for this cross-project access that you grant the appropriate access to (rather than granting that access to the default App Engine service account). Then, in your code that calls the API, you would explicitly use that service account by calling the useServiceAccountCredential() method of RemoteApiOptions to ensure that the API requests that are issued use the specified service account rather than the default App Engine service account.

Sending notifications One to One (Firebase) [duplicate]

I am thinking about keeping all registration ids(push token) in DB and sending notifications to user from iPhone. I tried something like this but did not get any notification.
func sendPNMessage() {
FIRMessaging.messaging().sendMessage(
["body": "hey"],
to: TOKEN_ID,
withMessageID: "1",
timeToLive: 108)
}
What I am doing wrong or maybe it is impossible at all?
Currently it's not possible to send messages from the application itself.
You can send messages from the Firebase Web Console, or from a custom server using the server-side APIs.
What you might want to do is to contact a server (like via http call) and that server will send the message to the user.
This way ensure that the API-KEY of the server is protected.
PS: the sendMessage(..) api is called upstream feature, and can be used to send messages from your app to your server, if you server has an XMPP connection with the FCM server.
Yes you can send push notification through Firebase.Please make sure do NOT include the server-key into your client. There are ways "for not so great people" to find it and do stuff... The Proper way to achieve that is for your client to instruct your app-server to send the notification.
You have to send a HTTP-Post to the Google-API-Endpoint.
You need the following headers:
Content-Type: application/json
Authorization: key={your_server_key}
You can obtain your server key within in the Firebase-Project.
HTTP-Post-Content: Sample
{
"notification": {
"title": "Notification Title",
"text": "The Text of the notification."
},
"project_id": "<your firebase-project-id",
"to":"the specific client-device-id"
}
Google Cloud Functions make it now possible send push notifications from device-to-device without an app server.
From the Google Cloud Functions documentation:
Developers can use Cloud Functions to keep users engaged and up to
date with relevant information about an app. Consider, for example, an
app that allows users to follow one another's activities in the app.
In such an app, a function triggered by Realtime Database writes to
store new followers could create Firebase Cloud Messaging (FCM)
notifications to let the appropriate users know that they have gained
new followers.
Example:
The function triggers on writes to the Realtime Database path where followers are stored.
The function composes a message to send via FCM.
FCM sends the notification message to the user's device.
Here is a demo project for sending device-to-device push notifications with Firebase and Google Cloud Functions.
Diego's answer is very accurate but there's also cloud functions from firebase it's very convenient to send notifications in every change in the db. For example let's say you're building chat application and sending notification in every new follower change.
This function sample is very good example.
For more information about cloud functions you can check official docs.
I have an app that has a "send feedback to developer" section. I also have a User collection in my firestore database. When a user logs into the app, I have that Users data update their FCM token with the following code in my SceneDelegate.swift:
import Firebase
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
authListener = Auth.auth().addStateDidChangeListener({ (auth, user) in
Auth.auth().removeStateDidChangeListener(self.authListener!)
if user != nil {
DispatchQueue.main.async {
let docRef = Firestore.firestore().collection("User").document((user?.email)!)
docRef.getDocument { (snapshot, error) in
guard let snapshot = snapshot else {return}
Messaging.messaging().token { token, error in
if let error = error {
print("Error fetching FCM registration token: \(error)")
} else if let token = token {
docRef.updateData(["FCMtoken":token])
print("FCM registration token: \(token)")
}
}
}
}
}
})
guard let _ = (scene as? UIWindowScene) else { return }
}
then in my feedback view controller i have this code to send my specific device (but you can look up/fetch which specific device you want in your database where the FCMtoken is stored where i have INSERT-DEVICE-TOKEN-HERE). The url to send to is "https://fcm.googleapis.com/fcm/send" and you can find YOUR-APP-FCM-KEY by going to your project settings in firebase, going to cloud messaging tab and its the server key.
func sendMePushNotification() {
let token = "INSERT-DEVICE-TOKEN-HERE"
if let url = URL(string: "https://fcm.googleapis.com/fcm/send") {
var request = URLRequest(url: url)
request.allHTTPHeaderFields = ["Content-Type":"application/json", "Authorization":"key=YOUR-APP-FCM-KEY"]
request.httpMethod = "POST"
request.httpBody = "{\"to\":\"\(token)\",\"notification\":{\"title\":\"Feedback Sent!\",\"body\":\"\(self.feedbackBox.text!)\",\"sound\":\"default\",\"badge\":\"1\"},\"data\": {\"customDataKey\": \"customDataValue\"}}".data(using: .utf8)
URLSession.shared.dataTask(with: request) { (data, urlresponse, error) in
if error != nil {
print("error")
} else {
print("Successfully sent!.....")
}
}.resume()
}
}
Use onesignal,you can send device to notifications or device to segments ,it can work with firebase in this way
Use onesignal functions to create a specific id,save it in a firebase database ,then when the id can be put in another function that is used to send a notification
Notes: 1-i am using it in my apps with firebase works perfectly
2-i can submit that code,just someone comments so i can find this answer

ADAL 4 Android not passing client secret

I'll first say that I'm sure it is just me since people have probably got this to work out of the box without having to edit the ADAL 4 Android Library without editing the source.
When running the sample program and authenticating with a token I get an error from AZURE that it is not passing the client_secret in the message body. I can confirm that this is in fact the case - it is not passing the client_secret.
Although if I edit the OAuth2.java file and change the method buildTokenRequestMessage to something like the following the workflow works perfectly
public String buildTokenRequestMessage(String code) throws UnsupportedEncodingException {
String message = String.format("%s=%s&%s=%s&%s=%s&%s=%s&%s=%s",
AuthenticationConstants.OAuth2.GRANT_TYPE,
StringExtensions.URLFormEncode(AuthenticationConstants.OAuth2.AUTHORIZATION_CODE),
AuthenticationConstants.OAuth2.CODE, StringExtensions.URLFormEncode(code),
AuthenticationConstants.OAuth2.CLIENT_ID,
StringExtensions.URLFormEncode(mRequest.getClientId()),
AuthenticationConstants.OAuth2.REDIRECT_URI,
StringExtensions.URLFormEncode(mRequest.getRedirectUri())
// these are the two lines I've added to make it work
AuthenticationConstants.OAuth2.CLIENT_SECRET,
StringExtensions.URLFormEncode("<MY CLIENT SECRET>")
);
return message;
}
Am I doing something wrong? If not, what is the correct way to access the client secret?
My implementation is straight from the demo application with only changes being setting up the strings to match my endpoints.
Thanks
You need to register your app as a Native application at Azure AD portal. You don't need client secret for native app.

Categories

Resources