Я знаю, что могут быть проблемы при использовании одного и того же устройства для производства и разработки, в качестве альтернативы, когда речь идет о Push-уведомлениях и концентраторах уведомлений в Azure.
Способ, которым я настроил, для iOS такой:
- У меня есть один концентратор уведомлений в Azure, настроенный для производства, подключенный к одному веб-API, расположенному в Azure.
- Другой концентратор уведомлений в Azure, настроенный для разработки, подключен к другому веб-API, размещенному в Azure..
Когда я работаю с приложением в разработке, в AppDelegate.cs я просто регистрируюсь в центре разработки, например:
var client = new MobileServiceClient(AppConstants.AZURE_DEVELOPMENT_WEB_API_URL);
Когда приложение готово к производству, в AppDelegate.cs я регистрируюсь в центре уведомлений о работе, например:
var client = newMobileServiceClient(AppConstants.AZURE_PRODUCTION_WEB_API_URL)
;
Конечно, я изменяю ключ aps-среды Entitlements.plist для разработки или производства в зависимости от ситуации.
Некоторое время это работало хорошо, но теперь я получаюrror в этой строке:
try
{
// exception is triggered here:
await client.GetPush().RegisterAsync(deviceToken, templates);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
И ошибка такова:
2018-12-17 12:03:19.682 MyApp.iOS[7321:2007760] <!DOCTYPE html>
<html>
<head>
<title>The resource cannot be found.</title>
<meta name="viewport" content="width=device-width" />
<style>
body {font-family:"Verdana";font-weight:normal;font-size: .7em;color:black;}
p {font-family:"Verdana";font-weight:normal;color:black;margin-top: -5px}
b {font-family:"Verdana";font-weight:bold;color:black;margin-top: -5px}
H1 { font-family:"Verdana";font-weight:normal;font-size:18pt;color:red }
H2 { font-family:"Verdana";font-weight:normal;font-size:14pt;color:maroon }
pre {font-family:"Consolas","Lucida Console",Monospace;font-size:11pt;margin:0;padding:0.5em;line-height:14pt}
.marker {font-weight: bold; color: black;text-decoration: none;}
.version {color: gray;}
.error {margin-bottom: 10px;}
.expandable { text-decoration:underline; font-weight:bold; color:navy; cursor:hand; }
@media screen and (max-width: 639px) {
pre { width: 440px; overflow: auto; white-space: pre-wrap; word-wrap: break-word; }
}
@media screen and (max-width: 479px) {
pre { width: 280px; }
}
</style>
</head>
<body bgcolor="white">
<span><H1>Server Error in '/' Application.<hr width=100% size=1 color=silver></H1>
<h2> <i>The resource cannot be found.</i> </h2></span>
<font face="Arial, Helvetica, Geneva, SunSans-Regular, sans-serif ">
<b> Description: </b>HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
<br><br>
<b> Requested URL: </b>/push/installations/53de1cd2-8ba5-403e-950a-f4a1631a5fae<br><br>
<hr width=100% size=1 color=silver>
<b>Version
Information:</b> Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.7.3163.0
</font>
</body>
</html>
<!--
[HttpException]: The controller for path '/push/installations/53de1cd2-8ba5-403e-950a-f4a1631a5fae' was not found or does not implement IController.
at System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType)
at System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext requestContext, String controllerName)
at System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory)
at System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state)
at System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state)
at System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncC
allback cb, Object extraData)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.<>c__DisplayClass285_0.<ExecuteStepImpl>b__0()
at System.Web.HttpApplication.StepInvoker.Invoke(Action executionStep)
at System.Web.HttpApplication.StepInvoker.<>c__DisplayClass4_0.<Invoke>b__0()
at Microsoft.AspNet.TelemetryCorrelation.TelemetryCorrelationHttpModule.OnExecuteRequestStep(HttpContextBase context, Action step)
at System.Web.HttpApplication.<>c__DisplayClass284_0.<OnExecuteRequestStep>b__0(Action nextStepAction)
at System.Web.HttpApplication.StepInvoker.Invoke(Action executionStep)
at System.Web.HttpApplication.ExecuteStepImpl(IExecutionStep step)
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
--><!--
This error page might contain sensitive information because ASP.NET is configured to show verbose error messages using <customErrors mode="Off"
/>. Consider using <customErrors mode="On"/> or <customErrors mode="RemoteOnly"/> in production environments.-->
Thread finished: <Thread Pool> #13
The thread 0xd has exited with code 0 (0x0).
Вот код в моем AppDelegate.cs:
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
// This MobileServiceClient has been configured to communicate with the Azure Mobile App and
// Azure Gateway using the application url. You're all set to start working with your Mobile App!
//Microsoft.WindowsAzure.MobileServices.MobileServiceClient MyAppClient = new Microsoft.WindowsAzure.MobileServices.MobileServiceClient(
//"https://myapp.azurewebsites.net");
global::Xamarin.Forms.Forms.Init();
//add azure support
CurrentPlatform.Init();
//add for using local database
string dbName = "shakealarm_db.sqlite";
string dbFolderPath = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), "..", "Library");
string dbFullPath = Path.Combine(dbFolderPath, dbName);
//load application with overloaded constructor for local db path --> add dbFullPath as param to new App()
LoadApplication(new App(dbFullPath, null));
// first request permission to use push notifications
RequestPushPermissionAsync();
// going to store the contents of the notification in the options param
// extract the content when app is active
_launchOptions = options;
return base.FinishedLaunching(app, options);
}
public override void OnActivated(UIApplication uiApplication)
{
base.OnActivated(uiApplication);
//If app was not running and we come from a notification badge, the notification is
if (_launchOptions != null && _launchOptions.ContainsKey(UIApplication.LaunchOptionsRemoteNotificationKey))
{
var notification = _launchOptions[UIApplication.LaunchOptionsRemoteNotificationKey] as NSDictionary;
PresentNotification(notification);
}
_launchOptions = null;
}
private async Task RequestPushPermissionAsync()
{
// Register for any type of notification (local or remote)
var requestResult = await UNUserNotificationCenter.Current.RequestAuthorizationAsync(
UNAuthorizationOptions.Alert
| UNAuthorizationOptions.Badge
| UNAuthorizationOptions.Sound);
// request result produces two items, item1 and item2
// Item1 = approved boolean
bool approved = requestResult.Item1;
NSError error = requestResult.Item2;
if (error == null)
{
//Handle approval
if (!approved)
{
Console.Write("Permission to receive notifications was not granted.");
return;
}
// check if settings have been modified since last run to disallow permission for push notif.
var currentSettings = await UNUserNotificationCenter.Current.GetNotificationSettingsAsync();
if (currentSettings.AuthorizationStatus != UNAuthorizationStatus.Authorized)
{
Console.WriteLine("Permissions were requested in the past but have been revoked(from settings)");
return;
}
// finally register for push notifications
// starts an asycrhonous process, receives a token
UIApplication.SharedApplication.RegisterForRemoteNotifications();
}
else
{
Console.Write($"Error requesting permissions: {error}.");
}
}
public async override void RegisteredForRemoteNotifications(
UIApplication application, NSData deviceToken)
{
if (deviceToken == null)
{
// can happen in rare conditions
return;
}
Console.WriteLine($"Token received: {deviceToken}");
await SendRegistrationToServerAsync(deviceToken);
}
private async Task SendRegistrationToServerAsync(NSData deviceToken)
{
//this is the template/payload used by iOS. It contains the "messageParam"
// that will be replaced by our service
const string templateBodyAPNS = @"{
""aps"" : {
""alert"" : ""$(messageParam)"",
""mutable-content"": 1
},
}";
var templates = new JObject();
templates["genericMessage"] = new JObject
{
{"body", templateBodyAPNS }
};
// send registration to web api for PRODUCTION
// var client = new MobileServiceClient(MyApp.App.MobileServiceUrl);
// send registration to web api for DEVELOPMENT
var client = new MobileServiceClient(AppConstants.AZURE_DEVELOPMENT_WEB_API_URL);
try
{
// exception triggered here
await client.GetPush().RegisterAsync(deviceToken, templates);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
//get the installation id for Development
Console.WriteLine("Installation id1: " + client.GetPush().InstallationId.ToString());
}
Итак, яЯ почти уверен, что есть проблема с идентификатором установки, вызванным тем, что я скачал приложение из магазина, а затем использовал тот же iPhone в разработке, и для push-уведомлений есть смешанный идентификатор установки / регистрации, но что делать дальше?Как я могу сбросить идентификатор установки?
Любые предложения приветствуются.