quarta-feira, 29 de julho de 2015

PushNotification Services Iphone C# - Did you know MBaaS?

AAPT DUMP



aapt dump badging arquivo.apk

Output like this...


.png'
permission: name='android.permission.ACCESS_COARSE_LO
permission: name='android.permission.ACCESS_FINE_LOCA
permission: name='android.permission.ACCESS_LOCATION_
permission: name='android.permission.ACCESS_MOCK_LOCA
permission: name='android.permission.ACCESS_NETWORK_S
permission: name='android.permission.ACCESS_WIFI_STAT
permission: name='android.permission.INTERNET'
permission: name='android.permission.WRITE_EXTERNAL_S
permission: name='android.permission.READ_EXTERNAL_ST
implied-permission: name='android.permission.READ_EXT
re-group: label=''
s-feature: name='android.hardware.location'
s-implied-feature: name='android.hardware.location' r
on, requested android.permission.ACCESS_FINE_LOCATION
MANDS permission, and requested android.permission.AC
s-feature: name='android.hardware.location.gps'
s-implied-feature: name='android.hardware.location.gp
sion'
s-feature: name='android.hardware.location.network'
s-implied-feature: name='android.hardware.location.ne
permission'
s-feature: name='android.hardware.touchscreen'
s-implied-feature: name='android.hardware.touchscreen
s-feature: name='android.hardware.wifi'
s-implied-feature: name='android.hardware.wifi' reaso

-activities
rts-screens: 'small' 'normal' 'large' 'xlarge'
rts-any-density: 'true'
es: '--_--' 'ca' 'da' 'fa' 'ja' 'nb' 'de' 'af' 'bg' '
' 'ro' 'ar' 'fr' 'hr' 'sr' 'tr' 'cs' 'es' 'it' 'lt' '
BD' 'et-EE' 'ka-GE' 'ky-KG' 'km-KH' 'zh-HK' 'si-LK' '
IN' 'kn-IN' 'mr-IN' 'mn-MN' 'ne-NP' 'pt-BR' 'gl-ES' '

ties: '160' '213' '240' '320' '480' '640'
e-code: 'armeabi-v7a'




You should use this.

https://github.com/Redth/PushSharp/

The code bellow are equals this post..


POST https://android.googleapis.com/gcm/send
Sender:  id=166630931688
Authorization:  key=AIzaSyDk5h0rBwEldoaW4fdR6gFNgYXO9vy67mg
Content-Type: application/x-www-form-urlencoded;charset=UTF-8
delay_while_idle=1&data.data=machineICITest&registration_id=APA91bG4DsBlVMnskukfHi2bDUr6gbgJquPYY4wYEwRQVhvRfWt66I7gc0Xryqfjh-AXVS7eCkiBIvphLsYBjBysRDNvrpsWYUcF5XPSfcqy5lnsTiIRDC-Tsyw3nalU1jD1Vf-fSK-W
 



CLIENT_TO_APPLE_ANDROID


The client bellow can send a push notification to Apple for a generic config.

using System;
using PushSharp.Core;
using PushSharp.Apple;
using PushSharp;
using System.IO;
using System.Threading.Tasks;

namespace testeNotification
{
    class MainClass
    {
        static PushBroker push = new PushBroker ();
        static FeedbackService feedback = new FeedbackService ();

        public static string showmessage(string message){
            return string.Format ("{0}-{1}", System.DateTime.Now.ToString("dd/mm/yyyy hh:MM:ss"), message);
        }
        public static void Main (string[] args)
        {
            Console.WriteLine (showmessage("[run] - Initialize Server..."));
            push.OnNotificationSent += NotificationSent;
            push.OnChannelException += ChannelException;
            push.OnServiceException += ServiceException;
            push.OnNotificationFailed += NotificationFailed;
            push.OnDeviceSubscriptionExpired += DeviceSubscriptionExpired;
            push.OnDeviceSubscriptionChanged += DeviceSubscriptionChanged;
            push.OnChannelCreated += ChannelCreated;
            push.OnChannelDestroyed += ChannelDestroyed;
            feedback.OnFeedbackReceived += OnFeedbackReceived;
            feedback.OnFeedbackException += OnFeedbackException;
            Console.WriteLine (showmessage("[ok ]"));

            Console.WriteLine (showmessage("[run] - Open P12 Certificate..."));
            var certPassword = "&b91EC#121865497";
            var appleCert = File.ReadAllBytes(@"D:\OpenSSL-Win64\certdev\mycertificate.p12");
            ApplePushChannelSettings settings = new ApplePushChannelSettings(false, appleCert, certPassword,true);
            Console.WriteLine (showmessage(String.Format("[run] - Openning {0}:{1}...",settings.Host, settings.Port)));
            Console.WriteLine (showmessage("[ok ]"));

            Console.WriteLine (showmessage("[run] - Register Feedback Service..."));

            feedback.Run (settings); 
            push.RegisterAppleService(settings);
            Console.WriteLine (showmessage("[ok ]"));

            Enviar(false);
            Console.WriteLine (showmessage("[msg] - program terminated."));
            Console.ReadLine ();
            
        }
        public async static void Enviar(bool handShake)
        {

            //Just for Showing...
            if (handShake) {
                for (int i = 0; i <= 10; i++) {
                    string token = "ce8268a714f0705fde987aff416affd361f635841104d688ab1aa21cf918371f";
                    push.QueueNotification (new AppleNotification ()
                    .ForDeviceToken (token)
                    .WithAlert (String.Format ("LAPUINKA Communication HandShake: {0}", i.ToString ()))
                    .WithSound ("sound.caf")
                    .WithBadge (7));
                    await Task.Delay (10000);
                }
            }


            while (true) {

                Console.Write (showmessage("[input] - Please, type notification (ENTER to Quit): "));
                string notify = Console.ReadLine ().Trim ();

                // termina se ho premuto enter
                if (String.IsNullOrEmpty (notify))
                    break;

                //Para você entender, este item deverão ser recuperados de um WebService do LAPUINKA
                //Ex: FinalDeAno.ListarDevicesQueAceitamNotificacao()

                //Como eles foram parar lá? 
Por que no momento que o usuário abriu o App no Iphone/Ipad
                //o programador executou um método para gravar o ID no servidor do LAPUINKA
                //Ex: FinalDeAno.GravarDeviceQueAceitaNotificacao("ce8268a714f0705fde987aff416affd361f635841104d688ab1aa21cf918371f");

                string[] tokens = {
                    "ce8268a714f0705fde987aff416affd361f635841104d688ab1aa21cf918371f" ,//Ipad
                    "ff83a1bb37f128fa5a9e581b47867b9a35a5cec36da240ac4b2a4bbb624b3b0c" //iPhone
                };
                    foreach(string token in tokens){
                    Console.WriteLine (showmessage("[run] - Sending the message to " + token));
                    push.QueueNotification (new AppleNotification ()
                    .ForDeviceToken (token)
                    .WithAlert (notify)
                    .WithSound ("sound.caf")
                    .WithBadge (7));
                    Console.WriteLine ("[ok ] - The message will be sent in 1 or 5 seconds...");

                }

            }
            push.StopAllServices();




        }
        public static void OnFeedbackReceived(string token, DateTime timestamp)
        {
            AdLapuinkaonarLog ("OnFeedbackReceived: " +token);
        }

        public static void OnFeedbackException(Exception exc)
        {
            Adicionar ("OnFeedbackException: " + exc.Message);
        }
        public static void EnviaMensagem(string Token){
            push.QueueNotification(new AppleNotification()
                .ForDeviceToken(Token)

                .WithAlert("Hello world!")
                .WithSound("sound.caf")
                .WithBadge(7));
            push.StopAllServices();
        }
        public static void Adicionar(String Texto) {
            Texto = String.Format("{0}-{1}",System.DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss"),Texto);
            using (System.IO.StreamWriter file = new System.IO.StreamWriter(@"D:\OpenSSL-Win64\logs\notificationTest.txt"true))
            {
                file.WriteLine(Texto);
        
            }
        }
        public static void DeviceSubscriptionChanged(object sender, string oldSubscriptionId, string newSubscriptionId, INotification notification)
        {
            //Currently this event will only ever happen for Android GCM
            Adicionar("Device Registration Changed:  Old-> " + oldSubscriptionId + "  New-> " + newSubscriptionId + " -> " + notification);
        }

        public static void NotificationSent(object sender, INotification notification)
        {
            Adicionar("Sent: " + sender + " -> " + notification);
        }

        public static void NotificationFailed(object sender, INotification notification, Exception notificationFailureException)
        {
            Adicionar("Failure: " + sender + " -> " + notificationFailureException.Message + " -> " + notification);
        }

        public static void ChannelException(object sender, IPushChannel channel, Exception exception)
        {
            Adicionar("Channel Exception: " + sender + " -> " + exception);
        }

        public static void ServiceException(object sender, Exception exception)
        {
            Adicionar("Service Exception: " + sender + " -> " + exception);
        }

        public static void DeviceSubscriptionExpired(object sender, string expiredDeviceSubscriptionId, DateTime timestamp, INotification notification)
        {
            Adicionar("Device Subscription Expired: " + sender + " -> " + expiredDeviceSubscriptionId);
        }

        public static void ChannelDestroyed(object sender)
        {
            Adicionar("Channel Destroyed for: " + sender);
        }

        public static void ChannelCreated(object sender, IPushChannel pushChannel)
        {
            Adicionar("Channel Created for: " + sender);
        }
    }
}


IPAD/IPHONE POC

using Foundation;
using UIKit;

namespace appNotificationNew
{
    // The UIApplicationDelegate for the application. This class is responsible for launching the
    // User Interface of the application, as well as listening (and optionally responding) to application events from iOS.
    [Register ("AppDelegate")]
    public class AppDelegate : UIApplicationDelegate
    {
        // class-level declarations
        // class-level declarations
        UIWindow window;
        UINavigationController navController;

        public override UIWindow Window {
            get;
            set;
        }

        public override bool FinishedLaunching (UIApplication application, NSDictionary launchOptions)
        {
            // Override point for customization after application launch.
            // If not required for your application you can safely delete this method

            // Code to start the Xamarin Test Cloud Agent
            #if ENABLE_TEST_CLOUD
            Xamarin.Calabash.Start();
            #endif
            // create a new window instance based on the screen size
            window = new UIWindow (UIScreen.MainScreen.Bounds);
            navController = new UINavigationController();


            // If you have defined a view, add it here:
            window.AddSubview (navController.View);


            // make the window visible
            window.MakeKeyAndVisible ();

            //Register for remote notifications
            if (UIDevice.CurrentDevice.CheckSystemVersion (80)) {
                var pushSettings = UIUserNotificationSettings.GetSettingsForTypes (
                    UIUserNotificationType.Alert | UIUserNotificationType.Badge | UIUserNotificationType.Sound,
                    new NSSet ());

                UIApplication.SharedApplication.RegisterUserNotificationSettings (pushSettings);
                UIApplication.SharedApplication.RegisterForRemoteNotifications ();
            } else {
                UIRemoteNotificationType notificationTypes = UIRemoteNotificationType.Alert | UIRemoteNotificationType.Badge | UIRemoteNotificationType.Sound;
                UIApplication.SharedApplication.RegisterForRemoteNotificationTypes (notificationTypes);
            }
            return true;
        }
    
        public override void RegisteredForRemoteNotifications (
            UIApplication application, NSData deviceToken)
        {
            // Get current device token
            var DeviceToken = deviceToken.Description;
            if (!string.IsNullOrWhiteSpace(DeviceToken)) {
                DeviceToken = DeviceToken.Trim('<').Trim('>');
            }

            // Get previous device token
            var oldDeviceToken = NSUserDefaults.StandardUserDefaults.StringForKey("PushDeviceToken");

            // Has the token changed?
            
if (string.IsNullOrEmpty(oldDeviceToken) || !oldDeviceToken.Equals(DeviceToken))
            {
                //TODO Aqui vem o ponto Crucial, enviar a Requisição para o WebService
                //Se não o seu servidor não tem como saber
                //Somente com esta lista de notificações o servidor irá saber quem irá notificar.

            }
            
new UIAlertView(DeviceToken ,"DeviceToken"null"OK"null).Show();
            // Save new device token 
            NSUserDefaults.StandardUserDefaults.SetString(DeviceToken, "PushDeviceToken");
        }

        public override void FailedToRegisterForRemoteNotifications (UIApplication application, NSError error)
        {

            new UIAlertView("Error registering push notifications", error.LocalizedDescription, null"OK"null).Show();

        }

        public void CreateLocal(string message){

            UILocalNotification notification = new UILocalNotification();
            NSDate.FromTimeIntervalSinceNow(1);
            //notification.AlertTitle = "Alert Title"; // required for Apple Watch notifications
            notification.AlertAction = "View Alert";
            notification.AlertBody = message;
            UIApplication.SharedApplication.ScheduleLocalNotification(notification);
        }
        public override void ReceivedRemoteNotification (UIApplication application, NSDictionary userInfo)
        {
            var aps = userInfo.ObjectForKey (new NSString (
                "aps")) as NSDictionary;
            var alert = aps.ObjectForKey (new NSString (
                "alert")).ToString ();
            var av = new UIAlertView("Notification:", alert, null"OK"null);
            av.Show ();
            //CreateLocal (alert);

        }
        public override void OnResignActivation (UIApplication application)
        {
            // Invoked when the application is about to move from active to inactive state.
            // This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) 
            // or when the user quits the application and it begins the transition to the background state.
            // Games should use this method to pause the game.
        }

        public override void DidEnterBackground (UIApplication application)
        {
            // Use this method to release shared resources, save user data, invalidate timers and store the application state.
            // If your application supports background exection this method is called instead of WillTerminate when the user quits.
        }

        public override void WillEnterForeground (UIApplication application)
        {
            // Called as part of the transiton from background to active state.
            // Here you can undo many of the changes made on entering the background.
        }

        public override void OnActivated (UIApplication application)
        {
            // Restart any tasks that were paused (or not yet started) while the application was inactive. 
            // If the application was previously in the background, optionally refresh the user interface.
        }

        public override void WillTerminate (UIApplication application)
        {
            // Called when the application is about to terminate. 
Save data, if needed. See also DidEnterBackground.
        }
    }
}

ANDROID CLIENT


using System.Text;
using Android.App;
using Android.Content;
using Android.Util;
using PushSharp.Client;
using Newtonsoft.Json;

//VERY VERY VERY IMPORTANT NOTE!!!!
// Your package name MUST NOT start with an uppercase letter.
// Android does not allow permissions to start with an upper case letter
// If it does you will get a very cryptic error in logcat and it will not be obvious why you are crying!
// So please, for the love of all that is kind on this earth, use a LOWERCASE first letter in your Package Name!!!!
[assembly: Permission(Name = "com.pushsharp.test.permission.C2D_MESSAGE")] //, ProtectionLevel = Android.Content.PM.Protection.Signature)]
[assembly: UsesPermission(Name = "com.pushsharp.test.permission.C2D_MESSAGE")]
[assembly: UsesPermission(Name = "com.google.android.c2dm.permission.RECEIVE")]

//GET_ACCOUNTS is only needed for android versions 4.0.3 and below
[assembly: UsesPermission(Name = "android.permission.GET_ACCOUNTS")]
[assembly: UsesPermission(Name = "android.permission.INTERNET")]
[assembly: UsesPermission(Name = "android.permission.WAKE_LOCK")]

namespace PushSharp.ClientSample.MonoForAndroid
{
    //You must subclass this!
    [BroadcastReceiver(Permission=GCMConstants.PERMISSION_GCM_INTENTS)]
    [IntentFilter(new string[] { GCMConstants.INTENT_FROM_GCM_MESSAGE }, Categories = new string[] { "com.pushsharp.test" })]
    [IntentFilter(new string[] { GCMConstants.INTENT_FROM_GCM_REGISTRATION_CALLBACK }, Categories = new string[] { "com.pushsharp.test" })]
    [IntentFilter(new string[] { GCMConstants.INTENT_FROM_GCM_LIBRARY_RETRY }, Categories = new string[] { "com.pushsharp.test" })]
    public class PushHandlerBroadcastReceiver : PushHandlerBroadcastReceiverBase<PushHandlerService>
    {
        //IMPORTANT: Change this to your own Sender ID!
        //The SENDER_ID is your Google API Console App Project ID.
        //  Be sure to get the right Project ID from your Google APIs Console.  It's not the named project ID that appears in the Overview,
        //  but instead the numeric project id in the url: eg: https://code.google.com/apis/console/?pli=1#project:166630931688:overview
        //  where 785671162406 is the project id, which is the SENDER_ID to use!
        public static string[] SENDER_IDS = new string[] {"166630931688"};

        public const string TAG = "PushSharp-GCM";
    }

    [Service//Must use the service tag
    public class PushHandlerService : PushHandlerServiceBase
    {
        public PushHandlerService() : base(PushHandlerBroadcastReceiver.SENDER_IDS) { }

        protected override void OnRegistered (Context context, string registrationId)
        {
            Log.Verbose(PushHandlerBroadcastReceiver.TAG, "GCM Registered: " + registrationId);
            //Send back to the server
            //    var wc = new WebClient();
            //    var result = wc.UploadString("http://your.server.com/api/register/", "POST", 
            //        "{ 'registrationId' : '" + registrationId + "' }");

            try{
                apnservico servico = new apnservico ();
                int ret = servico.RegisterDevice (registrationId, "Android","motox","notificationtest");
                if(ret==1)
                    Log.Info("PushHandlerService""servico.RegisterDevice-OK " + registrationId);    
                else
                    Log.Info("PushHandlerService""servico.RegisterDevice-NOT "+registrationId);    
            }
            catch(System.Exception ex){
                Log.Info("PushHandlerService""Error ao acessar WebService "+ex.Message);
            }

            createNotification("PushSharp-GCM Registered...""The device has been Registered, Tap to View!");
        }

        protected override void OnUnRegistered (Context context, string registrationId)
        {
            Log.Verbose(PushHandlerBroadcastReceiver.TAG, "GCM Unregistered: " + registrationId);
            //Remove from the web service
            //    var wc = new WebClient();
            //    var result = wc.UploadString("http://your.server.com/api/unregister/", "POST",
            //        "{ 'registrationId' : '" + lastRegistrationId + "' }");

            createNotification("PushSharp-GCM Unregistered...""The device has been unregistered, Tap to View!");

            try{
                apnservico servico = new apnservico ();
                int ret = servico.UnRegisterDevice (registrationId, "Android");
                if(ret==1)
                    Log.Info("PushHandlerService""servico.UnRegisterDevice-OK " + registrationId);    
                else
                    Log.Info("PushHandlerService""servico.UnRegisterDevice-NOT "+registrationId);    
            }
            catch(System.Exception ex){
                Log.Info ("PushHandlerService""Error ao acessar WebService " + ex.Message);
            }
        }

        protected override void OnMessage (Context context, Intent intent)
        {
            Log.Info(PushHandlerBroadcastReceiver.TAG, "GCM Message Received!");

            var msg = new StringBuilder();
            string msgAlert = "LAPUINKA Notification";

            if (intent != null && intent.Extras != null)
            {
                foreach (var key in intent.Extras.KeySet()) {
                    msg.AppendLine (key + "=" + intent.Extras.Get (key).ToString ());
                    if (key == "alert")
                        msgAlert = " LAPUINKA - " + intent.Extras.Get (key).ToString (); 
                }
            }

            //Store the message
            var prefs = GetSharedPreferences(context.PackageName, FileCreationMode.Private);
            var edit = prefs.Edit();
            edit.PutString("last_msg",System.DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss") +" - "+msg.ToString());
            edit.Commit();
            createNotification(msgAlert,msgAlert);
        }

        protected override bool OnRecoverableError (Context context, string errorId)
        {
            Log.Warn(PushHandlerBroadcastReceiver.TAG, "Recoverable Error: " + errorId);

            return base.OnRecoverableError (context, errorId);
        }

        protected override void OnError (Context context, string errorId)
        {
            Log.Error(PushHandlerBroadcastReceiver.TAG, "GCM Error: " + errorId);
        }

        void createNotification(string title, string desc)
        {
            //Create notification
            var notificationManager = GetSystemService(Context.NotificationService) as NotificationManager;

            //Create an intent to show ui
            var uiIntent = new Intent(thistypeof(DefaultActivity));

            //Create the notification
            var notification = new Notification(Android.Resource.Drawable.SymActionEmail, title);

            //Auto cancel will remove the notification once the user touches it
            notification.Flags = NotificationFlags.ShowLights;

            //Set the notification info
            //we use the pending intent, passing our ui intent over which will get called
            //when the notification is tapped.
            notification.SetLatestEventInfo(this, title, desc, PendingIntent.GetActivity(this0, uiIntent, 0));

            //Show the notification
            notificationManager.Notify(1, notification);
        }
    }
}
Apple Firewall Rules


Desenvolvimento
Produção
gateway.sandbox.push.apple.com:2195
gateway.push.apple.com:2195
feedback.sandbox.push.apple.com:2196
feedback.push.apple.com:2196
  

Google Http( Proxy Autentication Required)

Send a message using GCM HTTP connection server protocol:
  https://gcm-http.googleapis.com/gcm/send
  Content-Type:application/json
  Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA
  {
    "to": "/topics/foo-bar",
    "data": {
      "message": "This is a GCM Topic Message!",
     }
  }
 
If you have a proxy autentication, the PushSharp could not be worked. 


About Creating a Certificate Signing Request (CSR)

To manually generate a Certificate, you need a Certificate Signing Request (CSR) file from your Mac.

   
   

a) Download the Example openssl.cnf File from
https://access.redhat.com/documentation/en-US/Fuse_ESB/4.4.1/html/Web_Services_Security_Guide/files/i280763.html

b) Download openSSL from http://www.openssl.org/source/

c) Store the file openssl.cnf to d:\OpenSSL-Win64

d) Create Environment Variable at OPENSSL_CONF=d:/OpenSSL-Win64/openssl.cnf

e) openssl genrsa -out mykey.key 2048

f) opensql req -new -key mykey.key -out CertificateSigningRequest.certSigningRequest -subj "/emailAddress=lapuinka@gmail.com, CN=ALL4U, C=BR"

g) Add iOS Certificate on:

https://developer.apple.com/account/ios/certificate/certificateCreate.action

 Choose the What type of certificate do you need?

 [x] Apple Push Notification service SSL (Sandbox)

Done, Download the .cert file.



Download from Apple Cer File Ex: aps_development.cer



..\bin\openssl x509 -in aps_development.cer -inform DER -out aps_development.pem -outform PEM


[inform a password]
..\bin\openssl pkcs12 -export -inkey your.key -in aps_development.pem -out developer.p12






Other options

Azure Mobile Services (not tested)
Urban Airship (not tested)
Parse.com       (not tested)
Drawbacks



Another Tip for Facebook..

C:\Users\flapuinka>keytool -exportcert -alias androiddebugkey -keystore debug.keystore | d:openssl sha1 -binary | d:open
ssl base64

Postar um comentário