Huawei SMS retriever api is not working and Huawei devices - huawei-mobile-services

I am trying to retrieve OTP in Huawei device. but it is not working.
I have created the app in Huawei developer console with all the requirements.
Below is the code i am using to retrieve the sms.
private fun initSmsManager() {
val task = ReadSmsManager.start(this#MainActivity)
task.addOnCompleteListener {
if (task.isSuccessful) {
// The service is enabled successfully. Continue with the process.
Toast.makeText(this, "ReadSms service has been enabled.", Toast.LENGTH_LONG).show()
} else
Toast.makeText(this, "The service failed to be enabled.", Toast.LENGTH_LONG).show()
}
task.addOnSuccessListener(this, OnSuccessListener {
if(task.isSuccessful){
Toast.makeText(this, "ReadSms service has been enabled.", Toast.LENGTH_LONG).show()
myReceiver = MyBroadcastReceiver();
val intentFilter = IntentFilter(READ_SMS_BROADCAST_ACTION)
registerReceiver(myReceiver, intentFilter)
}
})
task.addOnFailureListener(this, OnFailureListener {
Toast.makeText(this,it.message,Toast.LENGTH_SHORT).show();
})
}
Broadcast receiver
class MyBroadcastReceiver : BroadcastReceiver() {
companion object {
val TAG = MyBroadcastReceiver::class.java.simpleName
}
override fun onReceive(context: Context?, intent: Intent?) {
val bundle = intent!!.extras
if (bundle != null) {
val status: Status? = bundle.getParcelable(ReadSmsConstant.EXTRA_STATUS)
if (status?.statusCode == CommonStatusCodes.TIMEOUT) {
// Service has timed out and no SMS message that meets the requirement is read. Service ended.
// doSomethingWhenTimeOut()
} else if (status?.statusCode == CommonStatusCodes.SUCCESS) {
if (bundle.containsKey(ReadSmsConstant.EXTRA_SMS_MESSAGE)) {
// An SMS message that meets the requirement is read. Service ended.
//doSomethingWhenGetMessage(bundle.getString(ReadSmsConstant.EXTRA_SMS_MESSAGE))
bundle.getString(ReadSmsConstant.EXTRA_SMS_MESSAGE)?.let {
Log.d(TAG, it)
val local = Intent()
local.action = "service.to.activity.transfer"
local.putExtra("sms", it)
context!!.sendBroadcast(local)
}
}
}
}
}
}
Any help in this would be beneficial.

Please confirm the following points:
Check whether the broadcast for receiving SMS verification codes is enabled. You can do that by performing breakpoint debugging or recording logs.
Check whether the SMS message format meets the rules for automatically reading SMS messages.
For details,See Docs.
Check whether the hash_value field is correct.
If no error occurs during the preceding check, could you pls provide a complete log trace then i will try to find out what can be wrong about this issue. :)

All code is working fine it works well on debug mode when I build released apk then keystore changed also hash changes for release mode. If you know anything about how to run on release mode , please let us know. Maybe some changes are made in Huawei developer account

Related

Invoke a method in flutter after restarting the device

I build a to-do list app that should show notifications to remind about tasks. In order to be able to schedule the notifications to the exact minute of the deadline, I pass the notifications data from flutter to kotlin, and showing the notification from a Broadcast receiver.
Here I am sending the notifications data to kotlin:
await platform.invokeMethod('setNextNotification', {
'tasksNames': tasksNames,
'notificationsTimeInMillis': notificationsTimeInMillis
});
This is how I get the data inside FlutterActivity:
private const val CHANNEL = "flutter.native/helper"
class MainActivity : FlutterActivity() {
companion object {
const val TASKS_NAMES_EXTRA = "tasksNames"
const val NOTIFICATIONS_TIME_IN_MILLIS_EXTRA = "notificationsTimeInMillis"
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
GeneratedPluginRegistrant.registerWith(this)
// Init the AlarmManager.
val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
// We got here from the setNotifications() method in flutter...
MethodChannel(flutterView, CHANNEL).setMethodCallHandler { call, result ->
if (call.method == "setNextNotification") {
// Get the time till next notification
val notificationsTimeInMillis: ArrayList<Long> = call.argument(NOTIFICATIONS_TIME_IN_MILLIS_EXTRA)
?: ArrayList()
// Create a pending intent for the notifications
val pIntent: PendingIntent? = createPendingIntent(call.argument(TASKS_NAMES_EXTRA), call.argument(TIME_LEFT_TEXTS_EXTRA), notificationsTimeInMillis, this)
// Cancel all alarms
while (alarmManager.nextAlarmClock != null)
alarmManager.cancel(alarmManager.nextAlarmClock.showIntent)
// Set the alarm
setAlarm(notificationsTimeInMillis[0], pIntent, alarmManager)
}
}
}
private fun setAlarm(notificationTime: Long, pIntent: PendingIntent?, alarmManager: AlarmManager) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { // The API is 23 or higher...
alarmManager.setAlarmClock(AlarmManager.AlarmClockInfo(notificationTime, pIntent), pIntent)
} else { // The API is 19 - 22...
// We want the alarm to go of on the exact time it scheduled for so we use the setExact method.
alarmManager.setExact(AlarmManager.RTC_WAKEUP, notificationTime, pIntent)
}
}
private fun createPendingIntent(tasksNames: ArrayList<String>?, timeTillNotificationsInMillis: ArrayList<Long>?,
context: Context): android.app.PendingIntent? {
return try {
val intent: android.content.Intent = android.content.Intent(context, AlarmManagerHelperWakeful::class.java)
intent.action = "notification"
intent.putStringArrayListExtra(TASKS_NAMES_EXTRA, tasksNames)
intent.putStringArrayListExtra(NOTIFICATIONS_TIME_IN_MILLIS_EXTRA, timeTillNotificationsInMillisAsString)
android.app.PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
} catch (e: java.lang.Exception) {
null
}
}
}
And this is how I show the notification on the BroadcastReceiver, and after that sets the next notification:
Class AlarmManagerHelperWakeful : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
if (intent != null && intent.action == "notification" && context != null) {
val tasksLabels: ArrayList<String> = intent.getStringArrayListExtra(MainActivity.TASKS_NAMES_EXTRA)
?: ArrayList()
val notificationsTimeInMillisAsString: ArrayList<String> = intent.getStringArrayListExtra(MainActivity.NOTIFICATIONS_TIME_IN_MILLIS_EXTRA)
?: ArrayList()
if (tasksLabels.size > 0) {
// Create a notification manager.
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
var builder = NotificationCompat.Builder(context) // The initialization is for api 25 or lower so it is deprecated.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // This is API 26 or higher...
// Create a channel for API 26 or higher;
val channelId = "channel_01" // The id of the channel.
if (notificationManager.getNotificationChannel(channelId) == null) {
val channel = NotificationChannel(channelId,
context.getString(R.string.notification_channel_name),
NotificationManager.IMPORTANCE_DEFAULT)
notificationManager.createNotificationChannel(channel)
}
// Update the builder to a no deprecated one.
builder = NotificationCompat.Builder(context, channelId)
}
// Set the notification details.
builder.setSmallIcon(android.R.drawable.ic_notification_overlay)
builder.setContentTitle(tasksLabels[0])
builder.setContentText(someText)
builder.priority = NotificationCompat.PRIORITY_DEFAULT
notificationId = someUniqueId
// Show the notification.
notificationManager.notify(notificationId.toInt(), builder.build())
// Remove this notification from the notifications lists.
tasksLabels.removeAt(0)
notificationsTimeInMillisAsString.removeAt(0)
// There are more notifications...
if (tasksLabels.size > 0) {
// Init the AlarmManager.
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
// Cancel all alarms
while (alarmManager.nextAlarmClock != null)
alarmManager.cancel(alarmManager.nextAlarmClock.showIntent)
// Create a pending intent for the notifications
val pIntent: PendingIntent? = createPendingIntent(tasksLabels, cnotificationsTimeInMillisAsString, context)
// Set the alarm
setAlarm(notificationsTimeInMillisAsString[0].toLong(), pIntent, alarmManager)
}
}
} else {
if (intent == null) {
Log.d("Debug", "Checking: intent == null")
} else if ( intent.action != "notification") {
Log.d("Debug", "Checking: intent.action != notification")
val tasksLabels: ArrayList<String> = intent.getStringArrayListExtra(MainActivity.TASKS_NAMES_EXTRA)
?: ArrayList()
Log.d("Debug", "Checking: tasksNames.size inside else if" + tasksLabels.size)
}
}
}
}
Everything works perfectly fine unless I restart my device. Then the Broadcast receiver gets an intent without any data. For the BoradcastReceiver to get intent with notifications data, I need to invoke the method from the flutter code (the method that sends notifications data to the kotlin code), which means that for now, the user has to enter the app for that. Otherwise, user will not see notifications until entering my app and reinvoking the flutter code.
How can I overcome that issue?
You should use Push Notification instead of sending local notification to your broadcast receiver. There're lot of cases that make your app cannot send local notification. ex: user closed app (lot of users alway close app after using), OS closed app or clean memory, Dart method is crashing.
Firebase FCM is pretty simple, it's much more simple than you solution that's using broadcast receiver. Also totally free.
https://pub.dev/packages/firebase_messaging
Pushwoosh is good too, it has schedule notification
https://pub.dev/packages/pushwoosh
Using push notification also has other pros that you app will also work on iOS, doesn't need to keep your app running on background which is very bad idea if your app doesn't have any special features that need to run background (music player, geo location, VOIP)
In case you don't want to use Push Notification. Take a look at this lib:
https://pub.dev/packages/flutter_local_notifications
Right now you are sending data from dart to the native plugin. You might try it the other way around. This example shows how you can get the native android reboot event. Next, you can use this example to fetch the required data. After fetching the data you can set the notification.
You could also try to store the information of the last notification in SharedPreferences, fetch that on boot, and set the notification.

Vertx: How to verify auth before handle body request?

How to verify auth before handle body request?
I'm using vertx:
vertxVersion = '3.8.3'
implementation "io.vertx:vertx-core:$rootProject.vertxVersion"
implementation "io.vertx:vertx-web:$rootProject.vertxVersion"
implementation "io.vertx:vertx-lang-kotlin:$rootProject.vertxVersion"
implementation "io.vertx:vertx-lang-kotlin-coroutines:$rootProject.vertxVersion"
implementation "io.vertx:vertx-mongo-client:$rootProject.vertxVersion"
implementation "io.vertx:vertx-auth-mongo:$rootProject.vertxVersion"
implementation "io.vertx:vertx-auth-jwt:$rootProject.vertxVersion"
I want to verify auth before handle body request. But I got error java.lang.IllegalStateException: Request has already been read
Reproduce by use delay on suspend function:
router.handler { context ->
launch {
context.request().setExpectMultipart(true)
delay(100) //This line is sample for a verify auth process
context.next()
}
}
.handler {context ->
println("2")
context.request()
.handler {
b -> println("buff ${b.length()}")
}
.endHandler {
println("end handle")
context.success("ok")
}
}.baseHandle(
fn
).failureHandler {
println("fail: ${it.failure()}")
it.error()
}
When run delay(100) (this's sample for a verify process), I got the error above. If I comment delay(100), It's will be working fine.
This happens because by the time you auhenticated the request, the content has kept arriving and has been dropped.
You need to invoke context.request().pause() in you first handler and then context.request().resume() when you're ready.
In most cases though it's easier to let the BodyHandler manage payload for you.
Finally, I did solve it.
My router is working with the flows:
router.post("/api/upload/file")
.baseHandle { checkAuthorization(it) }
.handleFileUpload { updateFileOnItem(it) }
And Following step:
fun checkAuthorization(context: RoutingContext) {
val request = context.request()
val tkCookie = request.getCookie("user")
...do something to verify user permission
request.pause()
context.next()
context.request().resume()
}
Next:
fun updateFileOnItem(context: RoutingContext) {
val file = context.fileUploads()
...do something
}
It's working with me. Hope it can be help you. Thanks!

How to set up and use the Kin blockchain in a Unity app - Step by step

What is a good step by step explanation on how to use the Kin Unity SDK in an empty project in Unity?
Option 1: Use a pre-made wrapper
Use the wrapper in this 10 minute set up code (client and server) and call it as follows:
kinWrapper.SendPayment(1.00M, "test send", address);
kinWrapper.Balance();
//etc
Here is a detailed tutorial on implmenting the wrapper.
Option 2: Create your own wrapper
The Kin blockchain is a fork of the stellar protocol. As such, operations in your app will boil down to the following:
Creating accounts on the blockchain
Funding accounts on the blockchain
Sending payments
You can clone a sample implementation here - or you can follow the steps below to get a basic understanding.
Installation
Create an empty Unity project, and install the Kin Unity Plugin and modify your gradle file as described here.
NOTE: The SDK only runs on an Android/iOS device or emulator. The SDK will not run in the unity editor or unity remote -so you will need to compile and run the code in an emulator or device.
Implementation
Create an empty MonoBehaviour script - name it KinWrapper, and declare the Kin namespace:
using Kin;
You can also enable blockchain listeners by adding the following to your MonoBehaviour :
public class KinWrapper : MonoBehaviour, IPaymentListener, IBalanceListener
Instantiating
Next declare instances of the Kin Client and Kin Account
private KinClient kinClient;
private KinAccount kinAccount;
The client handles the native code depending on the platform you are using. (Android or iOS). The account is the main interface you will be using.
Creating an account
Before using the account, you first have to instantiate it through the client.
kinClient = new KinClient(Kin.Environment.Test, "appId");
if (!kinClient.HasAccount())
{
kinAccount = kinClient.AddAccount();
}else{
kinAccount = kinClient.GetAccount(0);
}
The code above first checks to see if a local account exists on the device. If it doesn't, it creates an account on the device and returns that as a reference.
NOTE: A 'created account' is simply a public key and private key generated on the device. These local keys enable the device to communicate with the blockchain.
You can now get the public key (client's blockchain address) by calling:
kinAccount.GetPublicAddress();
Onboarding/ Funding an account
Because this key only exists locally, you need to 'on-board' it to the blockchain. In other words, a special function needs to be called, to fund and register it online. Before this step is done, the address is considered invalid on the blockchain, and cannot receive or make transactions. This is part of the stellar protocol to avoid spam and unnecessary account creation.
You can check if the account has been on-boarded and funded by calling the following function:
kinAccount.GetStatus(GetStatusCallback)
void GetStatusCallback(KinException ex, AccountStatus status)
{
if (status == AccountStatus.Created)
{
}
else
{
}
}
To on-board and fund an account on the test blockchain, you have 3 options:
Option 1: You can do this manually by pasting the address on Kin's friend-bot service. This will on-board the account for you automatically.
Option 2: You can call the friend-bot through your code as an http request
https://friendbot-testnet.kininfrastructure.com/?addr=address_here
public static IEnumerator FundAccount( string publicAddress, Action<bool> onComplete = null )
{
var url = "http://friendbot-testnet.kininfrastructure.com/?addr=" + publicAddress;
var req = UnityWebRequest.Get( url );
yield return req.SendWebRequest();
if( req.isNetworkError || req.isHttpError )
{
Debug.Log( req.error );
if( onComplete != null )
onComplete( false );
}
else
{
Debug.Log( "response code: " + req.responseCode );
Debug.Log( req.downloadHandler.text );
if( onComplete != null )
onComplete( true );
}
}
Option 3: You can use server side code to fund it yourself (which you must do in a production environment). Basically, your client will need to call your server and request to be on-boarded. Your server can then use Kin's python SDK or node SDK to perform the on-boarding.
Here is a handy python implementation or Node.js implementation you can use for your server.
Calling the implementation from Unity is as simple as follows:
public IEnumerator FundMe(decimal amount, Action<bool> fundCallback = null)
{
WWWForm form = new WWWForm();
form.AddField("address", kinAccount.GetPublicAddress());
form.AddField("amount", amount.ToString());
reqUrl = "http://address.to.your.server";
var req = UnityWebRequest.Post(reqUrl, form);
yield return req.SendWebRequest();
if (req.isNetworkError || req.isHttpError)
{
Debug.LogError(req.error);
fundCallback(false);
}
else
{
fundCallback(true);
}
}
NOTE: Kin has two blockchains. Production and Test. The test blockchain merely has "play currency" that you can run tests on without incurring costs. The production blockchain has real world value Kin
Calling Other Functions
GetBalance()
account.GetBalance(GetBalanceCallback);
void GetBalanceCallback(KinException ex, decimal balance)
{
if (ex == null)
{
Debug.Log( "Balance: " + balance );
}
else
{
Debug.LogError( "Get Balance Failed. " + ex );
}
}
DeleteAccount()
kinClient.DeleteAccount(0);
NOTE: GetBalance() needs a callback because it's communicating with the blockchain online. DeleteAccount() doesn't because it simply deletes the private and public keys on the client. Once deleted, these keys can not be recovered.
Handling transactions
Transactions have the following parameters:
Memo: an optional string with extra information.
Address: the address of the recipient
Amount: amount of Kin you are sending (excluding fees)
Fee: the fee you will pay for your transaction to be processed by the blockchain. The current fee is 100/100000 KIN. This fee protects the blockchain from spam.
NOTE: The fee is denominated in the smallest unit of Kin. (Quark). Just like the smallest unit of a dollar is a cent. So when calling a transaction, set the fee to 100 (quarks) - which is 100/100000 KIN. Setting the fee tells the blockchain you are explicitly agreeing to pay the transaction fee. If you set the fee too low, your transaction will be rejected.
You can view all transactions on Kin's blockchain at: https://laboratory.kin.org/index.html#explorer?resource=payments
To send a payment, first build the transaction locally :
kinAccount.BuildTransaction(address, amount, fee, memo, BuildTransactionCallBack);
Building a transaction performs several operations on the client to authorise it and sign it. After the transaction is built, use the following callback to send it to Kin's blockchain.
void BuildTransactionCallBack(KinException ex, Transaction transaction)
{
if (ex == null)
{
kinAccount.SendTransaction(transaction, SendTransactionCallback);
}
else
{
Debug.LogError("Build Transaction Failed. " + ex);
}
}
Once you have sent the transaction to Kin's blockchain, you can listen for the response, to make sure it went through correctly. A transaction typically takes less than 10 seconds to complete.
void SendTransactionCallback(KinException ex, String transactionId)
{
if (ex == null)
{
//Success
}
else
{
Debug.LogError("Send Transaction Failed. " + ex);
}
}
NOTE: You should use co-routines for functions that need to wait. This will prevent your code from hanging while waiting for responses, and will create a better user experience.
Sending transactions with zero fees
You can send transactions with zero fees by being whitelisted by the Kin Foundation. To get whitelisted, simply register with the Kin Developer Program. Once approved, you can perform an extra step to let your client send transactions with zero fees.
To send a zero-fee transaction after building the transaction:
The client will need to contact your whitelisted server.
Your server will approve/ sign the transaction and send it back to the client.
The client will then send this approved transaction to Kin's blockchain, and it will be processed for free.
We have already built the transaction, now we whitelist it
void BuildTransactionCallBack(KinException ex, Transaction transaction)
{
if (ex == null)
{
StartCoroutine(WhitelistTransaction(transaction, WhitelistTransactionCallback))
}
else
{
Debug.LogError("Build Transaction Failed. " + ex);
}
}
We are calling our whitelisted server to authorise the transaction
IEnumerator WhitelistTransaction(Transaction transaction, Action<string, string> onComplete)
{
var postDataObj = new WhitelistPostData(transaction);
var postData = JsonUtility.ToJson(postDataObj);
var rawPostData = Encoding.UTF8.GetBytes(postData);
// UnityWebRequest does not work correclty when posting a JSON string so we use a byte[] and a hacky workaround
var req = UnityWebRequest.Post(baseURL + whitelistURL, "POST");
req.SetRequestHeader("Content-Type", "application/json");
req.uploadHandler = new UploadHandlerRaw(rawPostData);
yield return req.SendWebRequest();
if (req.isNetworkError || req.isHttpError)
{
Debug.LogError(req.error);
onComplete(null, null);
}
else
{
onComplete(req.downloadHandler.text, transaction.Id);
}
}
Our server has approved the transaction and sent back a signed string. We now send this signed string to Kin's blockchain
void WhitelistTransactionCallback(string whitelistTransaction, string transactionId)
{
if (whitelistTransaction != null)
{
kinAccount.SendWhitelistTransaction(transactionId, whitelistTransaction, SendTransactionCallback);
}
else
{
Debug.LogError("Whitelisting Transaction Failed. ");
}
}
As usual, we wait to see if the transaction was successful
void SendTransactionCallback(KinException ex, String transactionId)
{
if (ex == null)
{
//Success
}
else
{
Debug.LogError("Send Transaction Failed. " + ex);
}
}
Before your server has been approved for whitelisting, you can use this pre-approved server in the TEST environment. http://34.239.111.38:3000/whitelist.
public static IEnumerator WhitelistTransaction( Transaction transaction, Action<string> onComplete = null )
{
var postDataObj = new WhitelistPostData( transaction );
var postData = JsonUtility.ToJson( postDataObj );
var rawPostData = Encoding.UTF8.GetBytes( postData );
// UnityWebRequest does not work correclty when posting a JSON string so we use a byte[] and a hacky workaround
var url = "http://34.239.111.38:3000/whitelist";
var req = UnityWebRequest.Post( url, "POST" );
req.SetRequestHeader( "Content-Type", "application/json" );
req.uploadHandler = new UploadHandlerRaw( rawPostData );
yield return req.SendWebRequest();
if( req.isNetworkError || req.isHttpError )
{
Debug.Log( req.error );
if( onComplete != null )
onComplete( null );
}
else
{
Debug.Log( "response code: " + req.responseCode );
Debug.Log( req.downloadHandler.text );
if( onComplete != null )
onComplete( req.downloadHandler.text );
}
}
Once approved, you can use the sample python implementation or Node.js implementation to approve transactions on your server. You can also use the node.js SDK.
Listening to events on the blockchain
You can add listeners to prevent your client from over-querying the blockchain. Simply add the following code
kinAccount.AddPaymentListener(this);
kinAccount.AddBalanceListener(this);
public void OnEvent(PaymentInfo data)
{
//Listening for incoming and outgoing payments
}
public void OnEvent(decimal balance)
{
//Listening for changes in client's balance
}
Putting it all together
You can find this code implemented on: https://github.com/hitwill/kin-sdk-unity-tutorial under the MIT license.
Developer Playbook
You can also check this Developer Playbook - for some higher level concepts of creating with Kin.
Best practices
UX
(placeholder)
Server side security
Here is a great writeup on server side security.
Client side security
(placeholder)
Reducing calls to the blockchain
(placeholder)

Wifi Direct - GO receives connection request

I have 2 P2P devices (android smartphones). They created a Wifi Direct Group. So, we have a Group owner and a Client. A third device appears, and wants to join the group sending a connection request to the GO. When this happens the GO BroadcastReceiver detects a disconnect. I would like to know if that is a normal behavior or I'm doing something wrong.
This is part of my BroadcastReceiver
else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION
.equals(action)) {
if (manager == null) {
return;
}
NetworkInfo networkInfo = (NetworkInfo) intent
.getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO);
WifiP2pInfo wifiP2pInfo = (WifiP2pInfo) intent
.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO);
WifiP2pGroup wifiP2pGroup = (WifiP2pGroup) intent
.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_GROUP);
if (networkInfo.isConnected()) {
// we are connected with the other device, request connection
// info to find group owner IP
} else {
// It's a disconnect
}
} else if ....

Apple Push Notification Gateway Connection, Notification not received

I am sending notifications many a time from my iOS application. For this i have used APNS-PHP library for sending it from server to Apple Push Notification Gateway.
Here is the code.
public function publishAPush($requestBody){
try {
$toUserId=$requestBody->{KEY_USERID};
$toUserType=$requestBody->{KEY_USERTYPE};
$soundFileName=$requestBody->{"sound"};
$badge=$requestBody->{"badge"};
$customMessage=$requestBody->{"custom"};
$alertMesssage=$requestBody->{"alert"};
if(!empty ($toUserId)){
$push = new ApnsPHP_Push(
ApnsPHP_Abstract::ENVIRONMENT_SANDBOX,
'file.pem');
// Set the Root Certificate Autority to verify the Apple remote peer
$push->setRootCertificationAuthority('entrust_root_certification_authority.pem');
// Connect to the Apple Push Notification Service
$push->connect();
// Instantiate a new Message with a single recipient
$message = new ApnsPHP_Message($deviceToken);
// Set badge icon to "3"
$message->setBadge($badgeCount);
// Set a simple welcome text
$message->setText($alertMesssage);
// Play the default sound
$message->setSound($soundFileName);
$message->setCustomProperty("custom", json_encode($customMessage));
$push->add($message);
// Send all messages in the message queue
$push->send();
// Disconnect from the Apple Push Notification Service
$push->disconnect();
// Examine the error message container
$aErrorQueue = $push->getErrors();
if (!empty($aErrorQueue)) {
Logger::getRootLogger()->error("Apple Server Error= " . $aErrorQueue);
}else{
Logger::getRootLogger()->info("Message Send successfully to " . $toUserId);
}
}
} catch (Exception $exc) {
Logger::getRootLogger()->error("Publish a Push= " . $exc);
}
}
But it happens that many a times I don't receive them, so what could be a possible solution for it. Is it because I am connecting and disconnecting it.
What would be a better way to write this code?
do you receive the token in the ios app correctly?
also, use this ( https://github.com/jPaolantonio/SimplePush/blob/master/simplepush.php ) short example and then modify it yourself.
this example is working for me.