I created finishlaunching() in AppDelegate.cs and RegisteredForRemoteNotifications() but when I try to get device token it does not call RegisteredForRemoteNotifications() and I created push notification using Urban airship and for Test, I need device token.
How can I get Device Token using RemoteNotification ?
AppDelegate.cs contains below code...
using System;
using System.Reflection;
using Test.Interfaces;
using Test.Interfaces.UAIntegration;
using Test.iOS.UAIntegration;
using TestWebAPI.Client;
using TestWebAPI.Models;
using TestWebAPI.Models.ResponseModels;
using CoreGraphics;
using Facebook.CoreKit;
using Foundation;
using GalaSoft.MvvmLight.Ioc;
using HockeyApp.iOS;
using UIKit;
using UrbanAirship;
using Xamarin.Forms.Platform.iOS;
using FacebookProfile = Facebook.CoreKit.Profile;
using FacebookSettings = Facebook.CoreKit.Settings;
using StoreKit;
using System.Diagnostics;
using Test.Services;
namespace Test.iOS
{
[Register("AppDelegate")]
public partial class AppDelegate : FormsApplicationDelegate
{
private NetworkManager _networkManager;
public override bool FinishedLaunching(UIApplication uiApplication, NSDictionary launchOptions)
{
UAirship.TakeOff();
RegisterServices();
//SetupHockeyAppSDK ();
SetupFacebookSDK();
FFImageLoading.Forms.Touch.CachedImageRenderer.Init();
var dummy = new FFImageLoading.Forms.Touch.CachedImageRenderer();
Xamarin.Forms.Forms.Init();
LoadApplication(new App());
UIApplication.SharedApplication.StatusBarHidden = false;
UIApplication.SharedApplication.SetStatusBarStyle(UIStatusBarStyle.LightContent, false);
_networkManager = new NetworkManager();
//HACK
OverrideDefaultListViewCustomActionsColors();
UAirship.Push().UserPushNotificationsEnabled = true;
//string chanelid = UAirship.Push().ChannelID;
//string token = UAirship.Push().DeviceToken;
new PhotoAccessChecker();
//return ApplicationDelegate.SharedInstance.FinishedLaunching(uiApplication, launchOptions);
return base.FinishedLaunching(uiApplication, launchOptions);
}
public override bool OpenUrl(UIApplication application, NSUrl url, string sourceApplication, NSObject annotation)
{
return ApplicationDelegate.SharedInstance.OpenUrl(application, url, sourceApplication, annotation);
}
void SetupFacebookSDK()
{
FacebookProfile.EnableUpdatesOnAccessTokenChange(true);
FacebookSettings.AppID = "983921778349321";
FacebookSettings.DisplayName = "Test – Test";
}
//void SetupHockeyAppSDK ()
//{
// BITHockeyManager.SharedHockeyManager.Configure ("88bf22ad3da341eab128b28cf316148f");
// BITHockeyManager.SharedHockeyManager.StartManager ();
// BITHockeyManager.SharedHockeyManager.Authenticator.AuthenticateInstallation ();
// BITHockeyManager.SharedHockeyManager.UpdateManager.AlwaysShowUpdateReminder = false;
//}
void RegisterServices()
{
SimpleIoc.Default.Register<IStatisticsCollector, FirebaseStatisticsCollector>(true);
SimpleIoc.Default.Register<HttpMessageHandlerFactory>();
SimpleIoc.Default.Register<ISettingsOpener, SettingsOpener>();
SimpleIoc.Default.Register<IPhotoAccessChecker, PhotoAccessChecker>();
SimpleIoc.Default.Register<IImageToStreamConverter, ImageToStreamConverter>();
SimpleIoc.Default.Register<IAuthenticationApiClient, AuthenticationApiClient>();
SimpleIoc.Default.Register<IUtilityApiClient, UtilityApiClient>();
SimpleIoc.Default.Register<IProfileApiClient, ProfileApiClient>();
SimpleIoc.Default.Register<IPaymentApiClient, PaymentApiClient>();
SimpleIoc.Default.Register<IInboxApiClient, InboxApiClient>();
SimpleIoc.Default.Register<IBlogApiClient, BlogApiClient>();
SimpleIoc.Default.Register<IUserSettings, UserSettings>();
SimpleIoc.Default.Register<IPreferences, Preferences>();
SimpleIoc.Default.Register<IEncryptor, Encryptor>();
SimpleIoc.Default.Register<ITimerFactory, TimerFactory>();
SimpleIoc.Default.Register<ISuggestionService<Location>, LocationService>();
SimpleIoc.Default.Register<ISuggestionService<Gender>, GenderService>();
SimpleIoc.Default.Register<ISuggestionService<Religion>, ReligionService>();
SimpleIoc.Default.Register<ISuggestionService<Diet>, DietService>();
SimpleIoc.Default.Register<ISuggestionService<Drink>, DrinkService>();
SimpleIoc.Default.Register<ISuggestionService<Smoke>, SmokeService>();
SimpleIoc.Default.Register<ISuggestionService<Occupation>, OccupationService>();
SimpleIoc.Default.Register<ISuggestionService<Education>, EducationService>();
SimpleIoc.Default.Register<ISuggestionService<MaritalStatus>, MaritalService>();
SimpleIoc.Default.Register<ISuggestionService<MemberTag>, TagsService>();
SimpleIoc.Default.Register<ISuggestionService<HeightFeet>, HeightFeetService>();
SimpleIoc.Default.Register<ISuggestionService<HeightInches>, HeightInchesService>();
SimpleIoc.Default.Register<ISuggestionService<BlockReason>, BlockReasonService>();
SimpleIoc.Default.Register<ISuggestionService<CancellationReason>, CancellationReasonService>();
SimpleIoc.Default.Register<ISuggestionService<HideProfileReason>, HideProfileReasonService>();
SimpleIoc.Default.Register<IDialogService, DialogService>();
SimpleIoc.Default.Register<ICropImageService, CropImageService>();
SimpleIoc.Default.Register<IFileService, FileService>();
SimpleIoc.Default.Register<INotificationService, NotificationService>();
SimpleIoc.Default.Register<IFacebookService, FacebookService>();
SimpleIoc.Default.Register<IUrbanAirshipService, UrbanAirshipService>();
SimpleIoc.Default.Register<IInAppService, InAppService>();
SimpleIoc.Default.Register<SuggestionServices>();
}
void OverrideDefaultListViewCustomActionsColors()
{
CGRect rect = new CGRect(0, 0, 1, 1);
CGSize size = rect.Size;
UIGraphics.BeginImageContext(size);
CGContext currentContext = UIGraphics.GetCurrentContext();
currentContext.SetFillColor(Colors.d8Red.ToCGColor());
currentContext.FillRect(rect);
var backgroundImage = UIGraphics.GetImageFromCurrentImageContext();
currentContext.Dispose();
var contextActionsCellType = Type.GetType("Xamarin.Forms.Platform.iOS.ContextActionsCell, Xamarin.Forms.Platform.iOS, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null");
// Now change the static field value!
var backgroundImageField = contextActionsCellType.GetField("DestructiveBackground", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
backgroundImageField.SetValue(null, backgroundImage);
rect = new CGRect(0, 0, 1, 1);
size = rect.Size;
UIGraphics.BeginImageContext(size);
currentContext = UIGraphics.GetCurrentContext();
currentContext.SetFillColor(Colors.d8Purple.ToCGColor());
currentContext.FillRect(rect);
backgroundImage = UIGraphics.GetImageFromCurrentImageContext();
currentContext.Dispose();
backgroundImageField = contextActionsCellType.GetField("NormalBackground", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
backgroundImageField.SetValue(null, backgroundImage);
}
public override void WillTerminate(UIApplication application)
{
(App.Locator.InApp.TheInAppService as InAppService).WillTerminate();
base.WillTerminate(application);
}
}
}
Related
I am trying to execute Xamarin App.
I can build and deploy solutions on both Android and iOS devices. But when I am Debugging/running iOS App I am receiving an error
**System.NullReferenceException:** 'Object reference not set to an instance of an object'
on
private static ILogger logger = DependencyService.Get<ILogManager>().GetLog(); line
I have installed the latest version of the Nlog NuGet Package.
My ILogManager file is
namespace VolMobile.AppData.Interfaces
{
public interface ILogManager
{
ILogger GetLog([System.Runtime.CompilerServices.CallerFilePath]string callerFilePath = "");
void Reload();
void DeleteLog();
}
}
How can I resolve this issue?
update
My NLogManager iOS file
using System;
using System.Collections.Generic;
using Xamarin.Forms;
using System.IO;
using NLog;
using NLog.Config;
using NLog.Targets;
using VolMobile.AppData.Interfaces;
using VolMobile.iOS.Logging;
[assembly: Dependency(typeof(NLogManager))]
namespace VolMobile.iOS.Logging
{
public class NLogManager : ILogManager
{
string logFile;
LoggingConfiguration config;
public NLogManager()
{
Reload();
}
public void Reload()
{
config = new LoggingConfiguration();
var consoleTarget = new ConsoleTarget();
config.AddTarget("console", consoleTarget);
var consoleRule = new LoggingRule("*", LogLevel.Trace, consoleTarget);
config.LoggingRules.Add(consoleRule);
//File logging level
LogLevel llSetting = LogLevel.Off;
IEnumerable<LogLevel> sysLevels = LogLevel.AllLevels;
//default to trace at startup
string currentLogLevel = "Trace";
//load the app state if available
if (App.AppState != null)
currentLogLevel = App.AppState.AppSettings.LogLevel;// AppData.AppData.LogLevel;
foreach (LogLevel ll in sysLevels)
{
if (currentLogLevel == ll.Name)
{
llSetting = ll;
}
}
var fileTarget = new FileTarget();
string folder = System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments); //android.os.environment is the other option
fileTarget.FileName = Path.Combine(folder, "Log.txt");
fileTarget.Layout = "${longdate}|${level:uppercase=true}|${callsite}|${appdomain}|${logger}|${threadid}|${message}|{exception:format=tostring}";
config.AddTarget("file", fileTarget);
logFile = Path.Combine(folder, "Log.txt");
var fileRule = new LoggingRule("*", llSetting, fileTarget);//LogLevel.Warn
config.LoggingRules.Add(fileRule);
LogManager.Configuration = config;
}
public void DeleteLog()
{
File.Delete(logFile);
}
// Services.Logging.ILogger
//AppData.Interfaces.ILogger
//public NLogLogger GetLog([System.Runtime.CompilerServices.CallerFilePath] string callerFilePath = "")
//{
// string fileName = callerFilePath;
// if (fileName.Contains("/"))
// {
// fileName = fileName.Substring(fileName.LastIndexOf("/", StringComparison.CurrentCultureIgnoreCase) + 1);
// }
// var logger = LogManager.GetLogger(fileName);
// return new NLogLogger(logger, logFile);
//}
public AppData.Interfaces.ILogger GetLog([System.Runtime.CompilerServices.CallerFilePath] string callerFilePath = "")
{
string fileName = callerFilePath;
if (fileName.Contains("/"))
{
fileName = fileName.Substring(fileName.LastIndexOf("/", StringComparison.CurrentCultureIgnoreCase) + 1);
}
var logger = LogManager.GetLogger(fileName);
return new NLogLogger(logger, logFile);
}
}
}
The app is working perfectly fine on iOS, Andriod simulators, and Android Device only not on iOS devices.
I am working on a xamarin forms app using xamarin forms maps for Android at the moment that tracks my location and depending on my proximity to a custom pin i have placed on the map will change in size depending on my proximity.
Basically if within a few meters the icon is 32x32 and farther away its 24x24.
Ive created a custom map renderer that places my pins from a JSON file and this is ok.
When my map form page loads in both my simulator and an actual android device the methods run and get my proximity based on my location and appropriately alter the size of the map pin.
However, this does not work as i move around.
For some reason my overridden CreateMarker method does not trigger when my location changes unless i call Content=customMap. Doing this only causes my map to load over and over and basically will not work.
I have a method in my about page called UpdateMap3() that is called when the users location changes. However, as stated i cant get the pins to update their size as i get nearer the pins while the app is running.
Ive included my forms page code behind below and markup below that and finally my map renderer below that.
Any help would be hugely appreciated.
Thanls
using System;
using System.IO;
using System.Reflection;
using Xamarin.Forms;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
using Xamarin.Forms.Maps;
using Xamarin.Essentials;
using Distance = Xamarin.Forms.Maps.Distance;
using Google.Protobuf.WellKnownTypes;
using static Google.Protobuf.Reflection.FieldDescriptorProto.Types;
namespace MAPS.Views
{
public partial class AboutPage : ContentPage
{
IlocationUpdateService loc;
public AboutPage()
{
InitializeComponent();
// Task.Delay(2000);
UpdateMap();
}
async void OnActionSheetCancelDeleteClicked()
{
bool answer = await DisplayAlert("Location Request", "Please enable location services to use this app", "Settings", "Cancel");
if (answer == true)
{
DependencyService.Get<ILocSettings>().OpenSettings();
}
}
protected override void OnAppearing()
{
base.OnAppearing();
bool gpsStat = DependencyService.Get<ILocSettings>().isGpsAvailable();
if (gpsStat == false)
{
OnActionSheetCancelDeleteClicked();
}
loc = DependencyService.Get<IlocationUpdateService>();
loc.LocationChanged += (object sender, ILocationEventArgs args) =>
{
String lat1 = args.Latitude.ToString();
String lng1 = args.Longitude.ToString();
//String lat1 = "55.099300";
// String lng1 = "-8.279740";
UpdateMap3(lat1, lng1); ;
};
loc.GetUsedLocation();
}
protected override void OnDisappearing()
{
base.OnDisappearing();
loc = null;
}
List<Place> placesList = new List<Place>();
private async void UpdateMap()
{
var assembly = IntrospectionExtensions.GetTypeInfo(typeof(AboutPage)).Assembly;
Stream stream = assembly.GetManifestResourceStream("MAPS.Places.json");
string text = string.Empty;
using (var reader = new StreamReader(stream))
{
text = reader.ReadToEnd();
}
var resultObject = JsonConvert.DeserializeObject<Places>(text);
var request = new Xamarin.Essentials.GeolocationRequest(GeolocationAccuracy.Best, TimeSpan.FromSeconds(30));
var location = await Geolocation.GetLocationAsync(request);
CustomMap customMap = new CustomMap()
{
IsShowingUser = true
};
customMap.CustomPins = new List<CustomPin>(); // put this before the foreach
foreach (var place in resultObject.results)
{
Location location1 = new Location(place.geometry.location.lat,place.geometry.location.lng);
// string color = getDist(location1, location);
string color = "purple";
if (color == "purple")
{
CustomPin pin = new CustomPin()
{
Type = PinType.Place,
Position = new Position(place.geometry.location.lat, place.geometry.location.lng),
Label = place.id,
Address = place.vicinity+"*",
Name = "Xamarin",
icon = "icon.png",
Url = "http://xamarin.com/about/"
};
customMap.Pins.Add(pin);
}
else
{
CustomPin pin = new CustomPin()
{
Type = PinType.Place,
Position = new Position(place.geometry.location.lat, place.geometry.location.lng),
Label = place.id,
Address = place.vicinity,
Name = "Xamarin",
icon = "pin.png",
Url = "http://xamarin.com/about/"
};
customMap.Pins.Add(pin);
}
}
customMap.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(location.Latitude, location.Longitude), Distance.FromKilometers(0.15))); ;
Content = customMap;
}
public string getDist(Location loc, Xamarin.Essentials.Location currentLoc)
{
string color = "red";
// bool geo = false;
double latEnd = loc.lat;
double lngEnd = loc.lng;
/// Position(currentLoc.lat, currentLoc.lng);
double dist = currentLoc.CalculateDistance(latEnd, lngEnd, DistanceUnits.Kilometers);
if (dist < 0.05) //5m distance
{
color = "purple";
}
else
{
color = "red";
}
return color;
}
public void getNewPins()
{
InitializeComponent();
}
public void getPin()
{
var pr = new PopUp();
}
private async void UpdateMap3(String lat, String lng)
{
var assembly = IntrospectionExtensions.GetTypeInfo(typeof(AboutPage)).Assembly;
Stream stream = assembly.GetManifestResourceStream("MAPS.Places.json");
string text = string.Empty;
using (var reader = new StreamReader(stream))
{
text = reader.ReadToEnd();
}
var resultObject = JsonConvert.DeserializeObject<Places>(text);
CustomMap customMap = new CustomMap()
{
IsShowingUser = true
};
customMap.CustomPins = new List<CustomPin>(); // put this before the foreach
foreach (var place in resultObject.results)
{
Location location1 = new Location(place.geometry.location.lat, place.geometry.location.lng);
Xamarin.Essentials.Location location = new Xamarin.Essentials.Location(Convert.ToDouble(lat), Convert.ToDouble(lng));
string color = getDist(location1, location);
if (color == "purple")
{
CustomPin pin2 = new CustomPin()
{
Type = PinType.Place,
Position = new Position(place.geometry.location.lat, place.geometry.location.lng),
Label = place.id,
Address = place.vicinity,
Name = "Xamarin",
icon = "icon.png",
Url = "http://xamarin.com/about/"
};
customMap.CustomPins = new List<CustomPin> {pin2};
customMap.Pins.Add(pin2);
}
else
{
CustomPin pin2 = new CustomPin()
{
Type = PinType.Place,
Position = new Position(place.geometry.location.lat, place.geometry.location.lng),
Label = place.id,
Address = place.vicinity+"*",
Name = "Xamarin",
icon = "pin.png",
Url = "http://xamarin.com/about/"
};
customMap.CustomPins = new List<CustomPin> { pin2 };
customMap.Pins.Add(pin2);
// Content.IsEnabled = true;
// customMap.CustomPins.Remove(pin);
}
}
// customMap.Pins.Clear();
// customMap.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(Convert.ToDouble(lat), Convert.ToDouble(lng)), Distance.FromKilometers(0.15))); ;
// Content = customMap;
// customMap.Pins.Add(pins);
}
}
}
Below is my forms page markup.
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MAPS;assembly=MAPS"
x:Class="MAPS.Views.AboutPage" Title="Explore">
<StackLayout>
<local:CustomMap x:Name="customMap" IsShowingUser="True"
MapType="Street" />
</StackLayout>
</ContentPage>
Below is my Android custom renderer
using Android.Content;
using Android.Gms.Maps;
using Android.Gms.Maps.Model;
using Android.Widget;
using MAPS;
using MAPS.Droid;
using MAPS.Views;
using Newtonsoft.Json;
using Rg.Plugins.Popup;
using Rg.Plugins.Popup.Animations;
using Rg.Plugins.Popup.Contracts;
using Rg.Plugins.Popup.Enums;
using Rg.Plugins.Popup.Services;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Xamarin.Forms;
using Xamarin.Forms.Maps;
using Xamarin.Forms.Maps.Android;
using static MAPS.Droid.CustomMapRenderer;
[assembly: ExportRenderer(typeof(CustomMap), typeof(CustomMapRenderer))]
namespace MAPS.Droid
{
public class CustomMapRenderer : Xamarin.Forms.Maps.Android.MapRenderer, GoogleMap.IInfoWindowAdapter
{
List<CustomPin> customPins;
public string popInfo;
public CustomMapRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(Xamarin.Forms.Platform.Android.ElementChangedEventArgs<Map> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
NativeMap.InfoWindowClick -= OnInfoWindowClick;
}
if (e.NewElement != null)
{
var formsMap = (CustomMap)e.NewElement;
customPins = formsMap.CustomPins;
Control.GetMapAsync(this);
}
}
protected override void OnMapReady(GoogleMap map)
{
base.OnMapReady(map);
NativeMap.InfoWindowClick += OnInfoWindowClick;
NativeMap.SetInfoWindowAdapter(this);
}
protected override MarkerOptions CreateMarker(Pin pin)
{
var marker = new MarkerOptions();
// CustomPin p = new CustomPin();
//foreach (var cp in customPins)
//{
// if (cp.Position == pin.Position)
// {
// p = cp;
// }
//}
marker.SetPosition(new LatLng(pin.Position.Latitude, pin.Position.Longitude));
marker.SetTitle(pin.Label);
// marker.SetIcon(BitmapDescriptorFactory.FromFile(p.icon));
if (pin.Address.Contains('*'))
{
marker.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.pin2));
}
else
{
marker.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.pin));
}
marker.Visible(true);
var a = NativeMap.AddMarker(marker);
a.ShowInfoWindow();
// marker.SetSnippet(pin.Address.Replace("*", " "));
return marker;
}
void OnInfoWindowClick(object sender, GoogleMap.InfoWindowClickEventArgs e)
{
getPlaceData(markerdata.markerData.title, markerdata.markerData.lat, markerdata.markerData.lng);
showPopUp();
}
public Android.Views.View GetInfoContents(Marker marker)
{
return null;
}
public void myMod(Marker marker)
{
}
public Android.Views.View GetInfoWindow(Marker marker)
{
markerdata.markerData.title = marker.Title;
markerdata.markerData.lat = marker.Position.Latitude.ToString("0.#####");
markerdata.markerData.lng = marker.Position.Longitude.ToString("0.#####");
// ds.Id = marker.Id;
// getPlaceData(marker.Title, marker.Position.Latitude.ToString("0.#####"), marker.Position.Longitude.ToString("0.#####"));
// showPopUp();
return null;
}
public string Number;
private async void showPopUp()
{
var Pr = new Views.PopUp();
var scaleAnimation = new ScaleAnimation
{
PositionIn = MoveAnimationOptions.Right,
PositionOut = MoveAnimationOptions.Left
};
Pr.Animation = scaleAnimation;
await PopupNavigation.PushAsync(Pr);
}
CustomPin GetCustomPin(Marker annotation)
{
return null;
}
private void getPlaceData(String name, String Lat, String Lng)
{
var assembly = IntrospectionExtensions.GetTypeInfo(typeof(AboutPage)).Assembly;
Stream stream = assembly.GetManifestResourceStream("MAPS.Places.json");
string text = string.Empty;
using (var reader = new StreamReader(stream))
{
text = reader.ReadToEnd();
}
var resultObject = JsonConvert.DeserializeObject<Places>(text);
foreach (var place in resultObject.results)
{
if((name==place.id)&&(Lat ==place.geometry.location.lat.ToString("0.#####"))&&(Lng ==place.geometry.location.lng.ToString("0.#####")))
{
getData.Instance.Id = place.id;
getData.Instance.lat = place.geometry.location.lat.ToString("0.#####");
getData.Instance.lng = place.geometry.location.lng.ToString("0.#####");
getData.Instance.marker2 = place.name;
getData.Instance.family = place.family;
getData.Instance.origin = place.Origin;
getData.Instance.date = place.Date;
getData.Instance.commonName = place.CommonName;
// getData.Instance.title = marker.Title;
}
}
}
}
}
Following code is working locally very fine.
The users receive All pushes (notifications) when I send them via local PC.
But I need use proxy on the server and this code fires the error: "Failed to establish a connection: Network is unreachable".
Plz help me setup the proxy for this code.
using System;
using MediatR;
using System.IO;
using FirebaseAdmin;
using System.Threading;
using System.Threading.Tasks;
using FirebaseAdmin.Messaging;
using Google.Apis.Auth.OAuth2;
namespace JMGlobal.Handlers
{
public class PushHandler : IRequestHandler<Request_Push, Response_Push>
{
public async Task<Response_Push> Handle(Request_Push request, CancellationToken cancellationToken)
{
try
{
var defaultApp = FirebaseApp.DefaultInstance;
if (defaultApp == null)
{
var keyPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "jKey.json");
defaultApp = FirebaseApp.Create(new AppOptions()
{
Credential = GoogleCredential.FromFile(keyPath),
// HttpClientFactory --- ????
});
}
var message = new Message()
{
Token = request.FirebaseToken,
Apns = new ApnsConfig()
{
Aps = new FirebaseAdmin.Messaging.Aps()
{
Alert = new ApsAlert()
{
Title = "push",
Body = request.PushMessage
}
}
},
Notification = new Notification
{
Title = "System Notification",
Body = $"Message: {request.PushMessage}"
}
};
var messaging = FirebaseMessaging.DefaultInstance;
var result = await messaging.SendAsync(message); // here fires the error: "Failed to establish a connection: Network is unreachable"
return new Response_Push()
{ .... };
}
catch (Exception ex)
{..... }
}
}
}
Working version below.
using System;
using MediatR;
using System.IO;
using FirebaseAdmin;
using System.Threading;
using System.Diagnostics;
using System.Threading.Tasks;
using FirebaseAdmin.Messaging;
using Google.Apis.Auth.OAuth2;
using System.Collections.Generic;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Google.Apis.Http;
using System.Net.Http;
using System.Net;
using Microsoft.Extensions.Options;
namespace JMGlobal.Handlers
{
public class ProxyHttpClientFactory2 : Google.Apis.Http.HttpClientFactory
{
private readonly string proxyAddress;
private readonly bool proxyUseProxy;
private readonly bool proxyBypassOnLocal;
public ProxyHttpClientFactory2(string proxyAddress, bool proxyUseProxy, bool proxyBypassOnLocal)
{
this.proxyAddress = proxyAddress;
this.proxyUseProxy = proxyUseProxy;
this.proxyBypassOnLocal = proxyBypassOnLocal;
}
protected override HttpMessageHandler CreateHandler(CreateHttpClientArgs args)
{
var proxy = new WebProxy(Address: proxyAddress, BypassOnLocal: proxyBypassOnLocal, BypassList: null, Credentials: null);
var webRequestHandler = new HttpClientHandler()
{
Proxy = proxy,
UseProxy = proxyUseProxy,
UseCookies = false
};
return webRequestHandler;
}
}
public class PushHandler : IRequestHandler<Request_PushFromBackend, Response_PushFromBackend>
{
private readonly IDBCommander _commander;
private readonly ILogger<PushHandler> _logger;
public PushFromBackendHandler(ILogger<PushHandler> logger, IDBCommander commander)
{
_logger = logger;
_commander = commander;
}
public async Task<Response_PushFromBackend> Handle(Request_PushFromBackend request, CancellationToken cancellationToken)
{
var sw = Stopwatch.StartNew();
bool isProxyUsing = false;
try
{
var resultFCMcreds = await _commander.Get_FCMcredentials(); // settings from DB
var resultProxy = await _commander.Get_ProxySettings(); // settings from DB
var defaultApp = FirebaseApp.DefaultInstance;
if (defaultApp == null)
{
var serviceAccountEmail = resultFCMcreds?.ServiceAccountEmail;
var PrivateKey = resultFCMcreds?.PrivateKey;
var credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
ProjectId = resultFCMcreds?.ProjectId,
HttpClientFactory = new ProxyHttpClientFactory2(resultProxy?.Address, (bool)resultProxy?.UseProxy, (bool)resultProxy?.BypassOnLocal),
}.FromPrivateKey(PrivateKey));
defaultApp = FirebaseApp.Create(new AppOptions()
{
Credential = GoogleCredential.FromServiceAccountCredential(credential),
HttpClientFactory = new ProxyHttpClientFactory2(resultProxy?.Address, (bool)resultProxy?.UseProxy, (bool)resultProxy?.BypassOnLocal)
});
}
FirebaseAdmin.Messaging.Aps aps_data = new Aps();
if (request.PushMode == 1)
{
aps_data.ContentAvailable = true;
}
var message = new Message()
{
//Topic = "news",
Token = request.FirebaseToken,
Apns = new ApnsConfig()
{
Aps = aps_data
},
Data = new Dictionary<string, string>()
{
["Changed"] = "true",
},
Notification = (request.PushMode == 1) ? null : new Notification
{
Title = $"System Notification {((request.PushMode == 1) ? " (SILENT)" : " (NORMAL)")}",
Body = $"Message: {request.PushMessage}"
}
};
var messaging = FirebaseMessaging.DefaultInstance;
var result = await messaging.SendAsync(message);
_logger.LogInformation($"result: {result}");
return new Response_PushFromBackend()
{
....
};
}
catch (Exception ex)
{
return new Response_PushFromBackend()
{
Error = ex.Message
};
}
}
}
}
I'm develop cross-platform mobile application that use NFC. I already check the xamarin android beam sample here. Now i'm trying implement the same sample using xamarin forms so i'm using dependency service to call the function from android project.
I already create Ndef message and send function:
using System;
using System.Text;
using Android.App;
using MyApp.Droid;
using Android.Nfc;
using Xamarin.Forms;
[assembly: Dependency(typeof(PhoneBeam))]
namespace MyApp.Droid
{
public class PhoneBeam : Activity, NfcAdapter.ICreateNdefMessageCallback, NfcAdapter.IOnNdefPushCompleteCallback, iBeam
{
private NfcAdapter nfcAdapter;
public void Beam()
{
nfcAdapter = NfcAdapter.GetDefaultAdapter(MainActivity.Instance);
nfcAdapter.SetNdefPushMessageCallback(this, MainActivity.Instance);
nfcAdapter.SetOnNdefPushCompleteCallback(this, MainActivity.Instance);
}
public NdefMessage CreateNdefMessage(NfcEvent evt)
{
DateTime time = DateTime.Now;
var text = ("Beam me up!\n\n" + "Beam : " +
time.ToString("HH:mm:ss"));
NdefMessage msg = new NdefMessage(
new NdefRecord[]{ CreateMimeRecord (
"application/com.companyname.MyApp",
Encoding.UTF8.GetBytes (text)) });
return msg;
}
public NdefRecord CreateMimeRecord(String mimeType, byte[] payload)
{
byte[] mimeBytes = Encoding.UTF8.GetBytes(mimeType);
NdefRecord mimeRecord = new NdefRecord(
NdefRecord.TnfMimeMedia, mimeBytes, new byte[0], payload);
return mimeRecord;
}
public void OnNdefPushComplete(NfcEvent e){}
}
}
However, I really don't know how to receive a message. In android beam sample, they implement it in mainactivity. Here's sample:
protected override void OnResume ()
{
base.OnResume ();
if (NfcAdapter.ActionNdefDiscovered == Intent.Action) {
ProcessIntent (Intent);
}
}
void ProcessIntent (Intent intent)
{
IParcelable [] rawMsgs = intent.GetParcelableArrayExtra (
NfcAdapter.ExtraNdefMessages);
NdefMessage msg = (NdefMessage) rawMsgs [0];
mInfoText.Text = Encoding.UTF8.GetString (msg.GetRecords () [0].GetPayload ());
}
So i want to implement in class file so i can use dependencyService. Is there a way to implement this?
Edit: I did the send function:
public NdefMessage CreateNdefMessage (NfcEvent evt)
{
DateTime time = DateTime.Now;
var text = ("Beam me up!\n\n" +
"Beam Time: " + time.ToString ("HH:mm:ss"));
NdefMessage msg = new NdefMessage (
new NdefRecord[] { CreateMimeRecord (
"application/com.companyname.MyApp", Encoding.UTF8.GetBytes (text))
});
return msg;
}
But it return as "NEW TAG COLLECTED: application/com.companyname.MyApp". I want to resume MyApp and show the message. But it didn't.
Is there a package that does screen capture in xamarin.forms ?
I need also to capture google maps screen shots
Check out this blog post by Daniel Hindrikes.
I'm going to assume that you use a PCL for your shared code.
You will need to create an interface in your PCL. He calls it IScreenshotManager. The declaration looks like this:
public interface IScreenshotManager
{
Task<byte[]> CaptureAsync();
}
Now all platforms will have their own implementation for it.
For iOS;
public class ScreenshotManager : IScreenshotManager
{
public async System.Threading.Tasks.Task<byte[]> CaptureAsync()
{
var view = UIApplication.SharedApplication.KeyWindow.RootViewController.View;
UIGraphics.BeginImageContext(view.Frame.Size);
view.DrawViewHierarchy(view.Frame, true);
var image = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
using(var imageData = image.AsPNG())
{
var bytes = new byte[imageData.Length];
System.Runtime.InteropServices.Marshal.Copy(imageData.Bytes, bytes, 0, Convert.ToInt32(imageData.Length));
return bytes;
}
}
}
For Android:
public class ScreenshotManager : IScreenshotManager
{
public static Activity Activity { get; set; }
public async System.Threading.Tasks.Task<byte[]> CaptureAsync()
{
if(Activity == null)
{
throw new Exception("You have to set ScreenshotManager.Activity in your Android project");
}
var view = Activity.Window.DecorView;
view.DrawingCacheEnabled = true;
Bitmap bitmap = view.GetDrawingCache(true);
byte[] bitmapData;
using (var stream = new MemoryStream())
{
bitmap.Compress(Bitmap.CompressFormat.Png, 0, stream);
bitmapData = stream.ToArray();
}
return bitmapData;
}
}
And for Windows Phone:
public class ScreenshotManager : IScreenshotManager
{
public async Task<byte[]> CaptureAsync()
{
var rootFrame = Application.Current.RootVisual as PhoneApplicationFrame;
var screenImage = new WriteableBitmap((int)rootFrame.ActualWidth, (int)rootFrame.ActualHeight);
screenImage.Render(rootFrame, new MatrixTransform());
screenImage.Invalidate();
using (var stream = new MemoryStream())
{
screenImage.SaveJpeg(stream, screenImage.PixelWidth, screenImage.PixelHeight, 0, 100);
var bytes = stream.ToArray();
return bytes;
}
}
}
Don't forget to register your platform specific implementations with the attribute which registers it with the Dependency Service, like this:
[assembly: Xamarin.Forms.Dependency (typeof (ScreenshotManager))]
It goes above the namespace declaration.
Now from your shared code you would be able to get the byte[] of a screenshot with a call like this:
var screenshotBytes = DependencyService.Get<IScreenshotManager>().CaptureAsync();
You probably want to check if DependencyService.Get<IScreenshotManager>() isn't null before using it.
After that you can turn your byte[] into an image and do whatever you like with it!
Implementation for UWP
public async Task<byte[]> CaptureAsync()
{
//create and capture Window
var renderTargetBitmap = new RenderTargetBitmap();
await renderTargetBitmap.RenderAsync(Window.Current.Content);
var pixelpuffer = await renderTargetBitmap.GetPixelsAsync();
var logicalDpi = DisplayInformation.GetForCurrentView().LogicalDpi;
IRandomAccessStream stream = new InMemoryRandomAccessStream();
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream);
encoder.BitmapTransform.InterpolationMode = BitmapInterpolationMode.Fant;
encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight, (uint)renderTargetBitmap.PixelWidth, (uint)renderTargetBitmap.PixelHeight, logicalDpi, logicalDpi, pixelpuffer.ToArray());
await encoder.FlushAsync();
byte[] resultingBuffer = new byte[stream.Size];
await stream.ReadAsync(resultingBuffer.AsBuffer(), (uint)resultingBuffer.Length, InputStreamOptions.None);
return resultingBuffer;
}