iOS How to get Firebase Device Token

This is the forum for miscellaneous technical/programming questions.

Moderator: 2ffat

iOS How to get Firebase Device Token

Postby Lena » Thu Apr 20, 2017 12:44 am

Hi.
In Android project all fine but in IOS FDeviceToken always empty.
Where could be the problem?
Code: Select all
#include <System.PushNotification.hpp>
//***
private:   // User declarations
   String FDeviceID;
   String FDeviceToken;

   TPushService * FPushService;
   TPushServiceConnection * FPushServiceConnection;

   void __fastcall OnReceiveNotificationEvent(TObject *Sender, TPushServiceNotification* const ANotification);
   void __fastcall OnServiceConnectionChange(TObject *Sender, TPushService::TChanges AChange);
   void __fastcall PushServiceRegister();
   void __fastcall RegisterDevice();


Code: Select all
#if defined(__APPLE__) && (defined(__arm__) || defined(__arm64__))
#include <FMX.PushNotification.IOS.hpp>

namespace Fmx {
 namespace Pushnotification {
  namespace Ios {
   _INIT_UNIT(Fmx_Pushnotification_Ios);
   }
  }
}

#endif

__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
{
  PushServiceRegister();
}

void __fastcall  TForm1::PushServiceRegister()
{

    FPushService = nullptr;
    FPushServiceConnection = nullptr;

   #if defined(__ANDROID__)
    FPushService = TPushServiceManager::Instance->GetServiceByName(TPushService_TServiceNames_GCM);
    if(FPushService)
      FPushService->AppProps[TPushService_TAppPropNames_GCMAppID] = FAndroidServerKey;
   #endif
   #if defined(__APPLE__) && (defined(__arm__) || defined(__arm64__))
      FPushService = TPushServiceManager::Instance->GetServiceByName(TPushService_TServiceNames_APS);
   #endif

   if(FPushService)
     {

      FPushServiceConnection = new TPushServiceConnection(FPushService);
      FPushServiceConnection->OnChange = &OnServiceConnectionChange;
      FPushServiceConnection->OnReceiveNotification = &OnReceiveNotificationEvent;
      FPushServiceConnection->Active = true;

      FDeviceID = FPushService->DeviceIDValue[TPushService_TDeviceIDNames_DeviceID];// OK!
      FDeviceToken = FPushService->DeviceTokenValue[TPushService_TDeviceTokenNames_DeviceToken];//Problem in IOS!

      if(FDeviceID != "" && FDeviceToken != "")
       {
        RegisterDevice();
       }

     }
}

Lena
BCBJ Master
BCBJ Master
 
Posts: 517
Joined: Sun Feb 06, 2011 1:28 pm

Re: iOS How to get Firebase Device Token

Postby rlebeau » Thu Apr 20, 2017 10:50 am

Lena wrote:In Android project all fine but in IOS FDeviceToken always empty.
Where could be the problem?


I found this:

https://community.embarcadero.com/answe ... nvey-parse

On iOS, the first time i call function below, I get a empty string. If I wait a second and try again, I get the right device token. So apparently, on iOS, activating PushServiceConnection (for the first time) will start a background process that takes some time before it results in a device token. This is a little bit mystic.


So, try calling FPushService->DeviceTokenValue[DeviceToken] in a loop until it returns a non-blank string, or until a few seconds have elapsed, whichever occurs first.
Remy Lebeau (TeamB)
Lebeau Software
User avatar
rlebeau
BCBJ Author
BCBJ Author
 
Posts: 1446
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA

Re: iOS How to get Firebase Device Token

Postby Lena » Fri Apr 21, 2017 1:41 am

or until a few seconds have elapsed


I use for this OnServiceConnectionChang:
Code: Select all
void __fastcall TForm1::OnServiceConnectionChange(TObject *Sender, TPushService::TChanges AChange)
{
   Label2->Text = L"Bihgo!";
   if (AChange.Contains(TPushService::TChange::DeviceToken) && (FPushServiceConnection))
   {
    Label2->Text = L"Again Bingo...";
    FDeviceID = FPushService->DeviceIDValue[TPushService_TDeviceIDNames_DeviceID];
    FDeviceToken =   FPushService->DeviceTokenValue[TPushService_TDeviceTokenNames_DeviceToken];

      if(FDeviceID != "" && FDeviceToken != "")
       {
        Label2->Text = L"Problem! I do not get here.";
        RegisterDevice();
       }

   }
}
Lena
BCBJ Master
BCBJ Master
 
Posts: 517
Joined: Sun Feb 06, 2011 1:28 pm

Re: iOS How to get Firebase Device Token

Postby Lena » Fri Apr 21, 2017 8:02 am

All my code:
Code: Select all
#include <System.Net.HttpClient.hpp>
#include <System.JSON.hpp>
#include <System.PushNotification.hpp>
//***
private:   // User declarations
   String FDeviceID;
   String FDeviceToken;

   TPushService * FPushService;
   TPushServiceConnection * FPushServiceConnection;

   void __fastcall OnReceiveNotificationEvent(TObject *Sender, TPushServiceNotification* const ANotification);
   void __fastcall OnServiceConnectionChange(TObject *Sender, TPushService::TChanges AChange);
   void __fastcall PushServiceRegister();
   void __fastcall RegisterDevice();


Code: Select all
#include <memory>
#include <System.Threading.hpp>

#if defined(__ANDROID__)
#include <FMX.PushNotification.Android.hpp>
#include <FMX.Platform.Android.hpp>

// Workaround for RSP-17714
namespace Fmx {
 namespace Pushnotification {
   namespace Android {
   _INIT_UNIT(Fmx_Pushnotification_Android);
   }
 }
} // End-of-Workaround

#endif

#if defined(__APPLE__) && (defined(__arm__) || defined(__arm64__))
#include <FMX.PushNotification.IOS.hpp>
#include <FMX.Platform.IOS.hpp>

// Workaround for RSP-17714
namespace Fmx {
 namespace Pushnotification {
  namespace Ios {
   _INIT_UNIT(Fmx_Pushnotification_Ios);
   }
  }
} // End-of-Workaround

#endif

const String FAndroidServerKey = L"820629486434"; //for Android
// ---------------------------------------------------------------------------
void ClearAllNotification()
{
  std::unique_ptr<TNotificationCenter> aNotificationCenter(new TNotificationCenter(NULL));
  if(aNotificationCenter->Supported())
   {
   aNotificationCenter->ApplicationIconBadgeNumber = -1;
   aNotificationCenter->CancelAll();
   }
}

// ---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
{
  ClearAllNotification();
  PushServiceRegister();
}
// ---------------------------------------------------------------------------

bool __fastcall CheckInet()
{
   bool result = false;
   THTTPClient *aHTTP = THTTPClient::Create();
   try {
      try {
         _di_IHTTPResponse aResp = aHTTP->Head("http://google.com");
         result = (aResp->StatusCode < 400);
      }
      catch (const System::Sysutils::Exception &E) {
         result = false;
      }
   }
   __finally {
      delete aHTTP;
   }
   return result;
}

// ---------------------------------------------------------------------------

#if defined(__APPLE__) && (defined(__arm__) || defined(__arm64__))
   String sPlatform = L"IOS";
#elif defined(__ANDROID__)
   String sPlatform = L"ANDROID";
#else
   String sPlatform = L"";
#endif

void __fastcall  TForm1::RegisterDevice()
{
   TTask::Run([this]()
    {
     String link = Format(_D("http://expert.um.la/pushTest/api.php?method=saveToken&deviceID=%s&deviceToken=%s&platform=%s"),
                        ARRAYOFCONST(( Form1->FDeviceID, Form1->FDeviceToken, sPlatform )));


     std::unique_ptr<THTTPClient> aHTTP(THTTPClient::Create());
     aHTTP->Get(link);
    }
   );
}

// ---------------------------------------------------------------------------

void __fastcall  TForm1::PushServiceRegister()
{
   bool result = CheckInet();
   if (result == true)
   {
    FPushService = nullptr;
    FPushServiceConnection = nullptr;

   #if defined(__ANDROID__)
    FPushService = TPushServiceManager::Instance->GetServiceByName(TPushService_TServiceNames_GCM);
    if(FPushService)
      FPushService->AppProps[TPushService_TAppPropNames_GCMAppID] = FAndroidServerKey;
   #endif
   #if defined(__APPLE__) && (defined(__arm__) || defined(__arm64__))
      FPushService = TPushServiceManager::Instance->GetServiceByName(TPushService_TServiceNames_APS);
   #endif

   if(FPushService)
     {

      FPushServiceConnection = new TPushServiceConnection(FPushService);
      FPushServiceConnection->OnChange = &OnServiceConnectionChange;
      FPushServiceConnection->OnReceiveNotification = &OnReceiveNotificationEvent;
      FPushServiceConnection->Active = true;

      FDeviceID = FPushService->DeviceIDValue[TPushService_TDeviceIDNames_DeviceID];
      FDeviceToken = FPushService->DeviceTokenValue[TPushService_TDeviceTokenNames_DeviceToken];

      if(FDeviceID != "" && FDeviceToken != "")
       {
        Label2->Text = L"TEST1";
        RegisterDevice();
       }

     }

   }//if (result == true)
}

// ---------------------------------------------------------------------------
void __fastcall TForm1::OnServiceConnectionChange(TObject *Sender, TPushService::TChanges AChange)
{
   if (AChange.Contains(TPushService::TChange::DeviceToken) && (FPushServiceConnection))
   {
    FDeviceID = FPushService->DeviceIDValue[TPushService_TDeviceIDNames_DeviceID];
    FDeviceToken =   FPushService->DeviceTokenValue[TPushService_TDeviceTokenNames_DeviceToken];

      if(FDeviceID != "" && FDeviceToken != "")
       {
        Label2->Text = L"TEST2";
        RegisterDevice();
       }

   }
}
// ---------------------------------------------------------------------------
void __fastcall TForm1::OnReceiveNotificationEvent(TObject *Sender,
   TPushServiceNotification* const ANotification)
{

 ClearAllNotification();

 const String FCMSignature = L"gcm.notification.body";
 const String GCMSignature = L"message";
 const String APNsSignature = L"alert";
 String aText = "";
 TJSONValue * aObj;

   #if defined(__ANDROID__)
      aObj = ANotification->DataObject->GetValue(GCMSignature);
      if(aObj != NULL)
         {
         aText = aObj->Value();
         }
         else
           {
            aText = ANotification->DataObject->GetValue(FCMSignature)->Value();
           }
   #endif

   #if defined(__APPLE__) && (defined(__arm__) || defined(__arm64__))
     aObj = ANotification->DataObject->GetValue(APNsSignature);
     if (aObj != NULL)
      {
      aText = aObj->Value();
      }
    #endif

 //ShowMessage(aText);

 if (NotificationCenter1->Supported() && aText != "")
  {
   TNotification * myNotification = NotificationCenter1->CreateNotification();

   __try
   {
     NotificationCenter1->CancelAll();
    myNotification->AlertBody = aText;
    NotificationCenter1->PresentNotification(myNotification);
   }
   __finally
         {
          myNotification->DisposeOf();
         }
  }

}


FDeviceToken in ios is empty. :(
Lena
BCBJ Master
BCBJ Master
 
Posts: 517
Joined: Sun Feb 06, 2011 1:28 pm

Re: iOS How to get Firebase Device Token

Postby rlebeau » Fri Apr 21, 2017 12:48 pm

Lena wrote:All my code:


Did you verify that the OnServiceConnectionChange event is being fired at all?

Did you try what I suggested earlier (using a simple loop instead of the event)? For example:

Code: Select all
FDeviceToken = FPushService->DeviceTokenValue[TPushService_TDeviceTokenNames_DeviceToken];

#if defined(__APPLE__) && (defined(__arm__) || defined(__arm64__))
if (FDeviceToken == _D(""))
{
    for (int i = 0; i < 5; ++i)
    {
        Sleep(1000); // <-- or whatever the iOS equivalent is...
        FDeviceToken = FPushService->DeviceTokenValue[TPushService_TDeviceTokenNames_DeviceToken];
        if (FDeviceToken != _D(""))
            break;
    }
}
#endif

...


Lena wrote:FDeviceToken in ios is empty. :(


If you can't get the token to work, then you will have to take up the issue with Embarcadero directly. File a bug report or open a Support case.
Remy Lebeau (TeamB)
Lebeau Software
User avatar
rlebeau
BCBJ Author
BCBJ Author
 
Posts: 1446
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA

Re: iOS How to get Firebase Device Token

Postby Lena » Fri Apr 21, 2017 11:04 pm

Did you verify that the OnServiceConnectionChange event is being fired at all?


Yes. I see text in Label2:
Code: Select all
void __fastcall TForm1::OnServiceConnectionChange(TObject *Sender, TPushService::TChanges AChange)
{
   if (AChange.Contains(TPushService::TChange::DeviceToken) && (FPushServiceConnection))
   {
    FDeviceID = FPushService->DeviceIDValue[TPushService_TDeviceIDNames_DeviceID];
    FDeviceToken =   FPushService->DeviceTokenValue[TPushService_TDeviceTokenNames_DeviceToken];
    Label2->Text = L"TEST before if";//OK
      if(FDeviceID != "" && FDeviceToken != "")
       {
        Label2->Text = L"TEST in if";//problem not fired
        RegisterDevice();
       }

   }
}



Did you try what I suggested earlier (using a simple loop instead of the event)?


Thank you I try but FDeviceToken still blank.

If you can't get the token to work, then you will have to take up the issue with Embarcadero directly. File a bug report or open a Support case.


Thank you. I will post in support and in Embarcadero forum. Maybe idera staff there read.
Lena
BCBJ Master
BCBJ Master
 
Posts: 517
Joined: Sun Feb 06, 2011 1:28 pm

Re: iOS How to get Firebase Device Token

Postby Lena » Tue Apr 25, 2017 9:01 am

Please vote: RSP-17939
Lena
BCBJ Master
BCBJ Master
 
Posts: 517
Joined: Sun Feb 06, 2011 1:28 pm

Re: iOS How to get Firebase Device Token

Postby Lena » Tue Jul 11, 2017 5:50 am

С++ Buillder still dead product to use notifications in IOS 10.
They do not work basic functions.
Lena
BCBJ Master
BCBJ Master
 
Posts: 517
Joined: Sun Feb 06, 2011 1:28 pm

Re: iOS How to get Firebase Device Token

Postby Lena » Thu Jul 13, 2017 2:02 am

I set correct provisioning profile and got FDeviceToken.
Now FDeviceToken is not NULL.
But when I try send push from Firebase to my IOS10 devise notthing happens.
Can sombody show how get push from FCM to IOS10 devise?
С++ Builder Berlin UP2.
Lena
BCBJ Master
BCBJ Master
 
Posts: 517
Joined: Sun Feb 06, 2011 1:28 pm


Return to Technical

Who is online

Users browsing this forum: Bing [Bot], Google [Bot] and 2 guests