問題
有些 XAML 的屬性是個列舉,可以設定多個列舉值,例如, FontAttributes 就是其中一列,可是,當我需要在 XAML 中定義多個列舉值的時候,我該如何定義呢?
解答
您可以參考底下用法,多個列舉值,可以使用逗號
,
將其分開即可 <Label Text="多奇數位創意有限公司" FontAttributes="Italic,Bold"/>
,
將其分開即可 <Label Text="多奇數位創意有限公司" FontAttributes="Italic,Bold"/>
Xamarin 工作紡
電子書中,也有交代如何透過 Xamarin.Auth ,進行市面上一般社群網站的 oAuth2 的身分驗證開發方法。MOBILESERVICESDOTNET_EXTENSION_VERSION
服務,最後的情況,當然也是一樣的,畫面被凍結了。Update the MOBILESERVICESDOTNET_EXTENSION_VERSION value from 1.0.478 to 1.0.479.
Facebook for iOS User-Agent string
: Mozilla/5.0 (iPhone; CPU iPhone OS 8_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Mobile/12D508 [FBAN/FBIOS;FBAV/27.0.0.10.12;FBBV/8291884;FBDV/iPhone7,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/8.2;FBSS/3; FBCR/vodafoneIE;FBID/phone;FBLC/en_US;FBOP/5]
string userAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 8_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Mobile/12D508 [FBAN/FBIOS;FBAV/27.0.0.10.12;FBBV/8291884;FBDV/iPhone7,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/8.2;FBSS/3; FBCR/vodafoneIE;FBID/phone;FBLC/en_US;FBOP/5]";
NSDictionary dictionary = NSDictionary.FromObjectAndKey(NSObject.FromObject(userAgent), NSObject.FromObject("UserAgent"));
NSUserDefaults.StandardUserDefaults.RegisterDefaults(dictionary);
Objective-C exception thrown. Name: NSInternalInconsistencyException Reason: Application windows are expected to have a root view controller at the end of application launch
刪去法
開始進行這類問題除錯。Info.plist
檔案內,加入底下的設定:<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
~/Library/MobileDevice/Provisioning\ Profiles
Google Cloud Messaging Client
元件XFDoggy.sln
專案Components
,選擇 Get More Components
Google Cloud Messaging Client
搜尋這個元件Google Cloud Messaging Client
元件,接著點選 Add to App
按鈕Infrastructure
資料夾,選擇 加入
> 類別
Visual C#
> Class
GcmService
新增
按鈕GcmService
類別請解析要加入的適當命名空間
public static string[] SENDER_IDS = new string[] { "300143732939" };
的 300143732939 文字,置換成為您申請到的 FCM 寄件者 ID
using Android.App;
using Android.Content;
using Android.Media;
using Android.Support.V4.App;
using Android.Util;
using Gcm.Client;
using Microsoft.WindowsAzure.MobileServices;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using XFDoggy.Helpers;
[assembly: Permission(Name = "@PACKAGE_NAME@.permission.C2D_MESSAGE")]
[assembly: UsesPermission(Name = "@PACKAGE_NAME@.permission.C2D_MESSAGE")]
[assembly: UsesPermission(Name = "com.google.android.c2dm.permission.RECEIVE")]
[assembly: UsesPermission(Name = "android.permission.INTERNET")]
[assembly: UsesPermission(Name = "android.permission.WAKE_LOCK")]
//GET_ACCOUNTS is only needed for android versions 4.0.3 and below
[assembly: UsesPermission(Name = "android.permission.GET_ACCOUNTS")]
namespace XFDoggy.Droid.Infrastructure
{
[Service]
public class GcmService : GcmServiceBase
{
public static string RegistrationID { get; private set; }
public GcmService()
: base(PushHandlerBroadcastReceiver.SENDER_IDS) { }
protected override void OnRegistered(Context context, string registrationId)
{
Log.Verbose("PushHandlerBroadcastReceiver", "GCM Registered: " + registrationId);
RegistrationID = registrationId;
var push = MainHelper.client.GetPush();
MainActivity.CurrentActivity.RunOnUiThread(() => Register(push, null));
}
public async void Register(Microsoft.WindowsAzure.MobileServices.Push push, IEnumerable<string> tags)
{
try
{
const string templateBodyGCM = "{\"data\":{\"message\":\"$(messageParam)\"}}";
JObject templates = new JObject();
templates["genericMessage"] = new JObject
{
{ "body", templateBodyGCM}
};
await push.RegisterAsync(RegistrationID, templates);
Log.Info("Push Installation Id", push.InstallationId.ToString());
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
Debugger.Break();
}
}
protected override void OnMessage(Context context, Intent intent)
{
Log.Info("PushHandlerBroadcastReceiver", "GCM Message Received!");
var msg = new StringBuilder();
if (intent != null && intent.Extras != null)
{
foreach (var key in intent.Extras.KeySet())
msg.AppendLine(key + "=" + intent.Extras.Get(key).ToString());
}
//Store the message
var prefs = GetSharedPreferences(context.PackageName, FileCreationMode.Private);
var edit = prefs.Edit();
edit.PutString("last_msg", msg.ToString());
edit.Commit();
string message = intent.Extras.GetString("message");
if (!string.IsNullOrEmpty(message))
{
createNotification("多奇數位創意通知", message);
return;
}
string msg2 = intent.Extras.GetString("msg");
if (!string.IsNullOrEmpty(msg2))
{
createNotification("New hub message!", msg2);
return;
}
createNotification("Unknown message details", msg.ToString());
}
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(this, typeof(MainActivity));
//Use Notification Builder
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
//Create the notification
//we use the pending intent, passing our ui intent over which will get called
//when the notification is tapped.
var notification = builder.SetContentIntent(PendingIntent.GetActivity(this, 0, uiIntent, 0))
.SetSmallIcon(Android.Resource.Drawable.SymActionEmail)
.SetTicker(title)
.SetContentTitle(title)
.SetContentText(desc)
//Set the notification sound
.SetSound(RingtoneManager.GetDefaultUri(RingtoneType.Notification))
//Auto cancel will remove the notification once the user touches it
.SetAutoCancel(true).Build();
//Show the notification
notificationManager.Notify(1, notification);
}
protected override void OnUnRegistered(Context context, string registrationId)
{
Log.Error("PushHandlerBroadcastReceiver", "Unregistered RegisterationId : " + registrationId);
}
protected override void OnError(Context context, string errorId)
{
Log.Error("PushHandlerBroadcastReceiver", "GCM Error: " + errorId);
}
}
[BroadcastReceiver(Permission = Gcm.Client.Constants.PERMISSION_GCM_INTENTS)]
[IntentFilter(new string[] { Gcm.Client.Constants.INTENT_FROM_GCM_MESSAGE }, Categories = new string[] { "@PACKAGE_NAME@" })]
[IntentFilter(new string[] { Gcm.Client.Constants.INTENT_FROM_GCM_REGISTRATION_CALLBACK }, Categories = new string[] { "@PACKAGE_NAME@" })]
[IntentFilter(new string[] { Gcm.Client.Constants.INTENT_FROM_GCM_LIBRARY_RETRY }, Categories = new string[] { "@PACKAGE_NAME@" })]
public class PushHandlerBroadcastReceiver : GcmBroadcastReceiverBase<GcmService>
{
public static string[] SENDER_IDS = new string[] { "300143732939" };
}
}
MainActivity.cs
GcmService
類別請解析要加入的適當命名空間
using System;
using Android.App;
using Android.Content.PM;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using Prism.Unity;
using Microsoft.Practices.Unity;
using System.Threading.Tasks;
using Microsoft.WindowsAzure.MobileServices;
using XFDoggy.Helpers;
using Gcm.Client;
using XFDoggy.Droid.Infrastructure;
[assembly: UsesPermission(Android.Manifest.Permission.AccessNetworkState)]
[assembly: UsesPermission(Android.Manifest.Permission.ReadExternalStorage)]
[assembly: UsesPermission(Android.Manifest.Permission.WriteExternalStorage)]
[assembly: UsesPermission(Android.Manifest.Permission.CallPhone)]
namespace XFDoggy.Droid
{
[Activity(Label = "多奇數位創意", Icon = "@drawable/icon", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity, IAuthenticate
{
#region Firebase 的推播設定用程式碼
// Create a new instance field for this activity.
static MainActivity instance = null;
// Return the current activity instance.
public static MainActivity CurrentActivity
{
get
{
return instance;
}
}
#endregion
#region Azure 行動應用之身分驗證用到程式碼
// Define a authenticated user.
private MobileServiceUser user;
public async Task<bool> Authenticate(MobileServiceAuthenticationProvider p登入方式)
{
// 驗證結果
var success = false;
// 要顯示的訊息
var message = string.Empty;
try
{
// 呼叫 Azure Mobile 用戶端的 LoginAsync 方法,依據指定的登入類型,進行身分驗證登入
user = await MainHelper.client.LoginAsync(this, p登入方式);
if (user != null)
{
message = string.Format("you are now signed-in as {0}.", user.UserId);
success = true;
}
}
catch (Exception ex)
{
message = ex.Message;
}
// 顯示登入成功或者失敗.
//AlertDialog.Builder builder = new AlertDialog.Builder(this);
//builder.SetMessage(message);
//builder.SetTitle("Sign-in result");
//builder.Create().Show();
return success;
}
#endregion
protected override void OnCreate(Bundle bundle)
{
TabLayoutResource = Resource.Layout.tabs;
ToolbarResource = Resource.Layout.toolbar;
base.OnCreate(bundle);
global::Xamarin.Forms.Forms.Init(this, bundle);
#region Azure 行動應用之身分驗證用到程式碼
// 將在 Android 原生平台實作的 IAuthenticate 物件,指定到 核心PCL 專案內
App.Init((IAuthenticate)this);
#endregion
#region Firebase 的推播設定用程式碼
// Set the current instance of MainActivity.
instance = this;
#endregion
LoadApplication(new App(new AndroidInitializer()));
#region Firebase 的推播設定用程式碼
try
{
// Check to ensure everything's set up right
GcmClient.CheckDevice(this);
GcmClient.CheckManifest(this);
// Register for push notifications
System.Diagnostics.Debug.WriteLine("Registering...");
GcmClient.Register(this, PushHandlerBroadcastReceiver.SENDER_IDS);
}
catch (Java.Net.MalformedURLException)
{
CreateAndShowDialog("There was an error creating the client. Verify the URL.", "Error");
}
catch (Exception e)
{
CreateAndShowDialog(e.Message, "Error");
}
#endregion
}
#region Firebase 的推播設定用程式碼
private void CreateAndShowDialog(String message, String title)
{
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.SetMessage(message);
builder.SetTitle(title);
builder.Create().Show();
}
#endregion
#region Firebase 的推播設定用程式碼
#endregion
}
public class AndroidInitializer : IPlatformInitializer
{
public void RegisterTypes(IUnityContainer container)
{
}
}
}
XamarinAzureDay 行動App
,並且開啟它XamarinAzureDay - 推送
刀鋒視窗中,點選 推送
連結
通知中樞
刀鋒視窗中,點選 + 通知中樞
通知中樞 新增通知中樞
刀鋒視窗中的 通知中樞 欄位,輸入 DoggyEnterpriseHub
或建立新的
新建立的命名空間
欄位中輸入 DoggyEnterpriseNamespace
釘到儀表板
,並點選 確定
按鈕通知中樞
部署完成建立專案
將Firebase加入您的Android應用程式
其中,套件名稱
可以點選滑鼠雙擊 Android 原生專案的Properties
節點,從Android Manifest
頁次中的Package Name
來取得關於偵錯簽署憑證 SHA-1
欄位,您可以開啟電腦中的 命令提示字元視窗,輸入:"C:\Program Files\Java\jdk1.8.0_102\bin\keytool" -exportcert -list -v -alias androiddebugkey -keystore "C:\Users\%username%\AppData\Local\Xamarin\Mono for Android\debug.keystore"其中keytool
這個工具您可以從您電腦中的 Java JDK 安裝路徑中找到您的除錯用的程式碼簽名檔案,將位於 C:\Users\%username%\AppData\Local\Xamarin\Mono for Android\debug.keystore執行結果如下所示,請複製 SHA1 的欄位值,貼到網頁上即可另外,預設密碼為 android
新增應用程式
按鈕繼續
按鈕完成
按鈕DoggyEnterprise
專案頁面中,點選齒輪圖示專案設定
CLOUD MESSENAGING
標籤頁次伺服器金鑰
/ 寄件者 ID
兩個欄位值複製起來,等下會用到設定推播通知服務
推播通知服務 DoggyEnterpriseHub
刀鋒視窗中,點選 `Google (GCM)Google (GCM) DoggyEnterpriseHub
刀鋒視窗內的 API 金鑰欄位,輸入在 Firebase 內取得的 伺服器金鑰
儲存
按鈕