iPhoneアプリのprovisioning profileの指定場所
iPhoneアプリを作成する場合、provisioning profileを作成する必要があるが、Visual Studioで開発を行う場合にも、XCode側でセットする必要がある。
XcodeメニューのPreverencesを開き、Accountsタグから、右下のView DetailsでProvisioning Profilesをダウンロードしておく必要がある。
ここまでやると、Visual StudioでiOSプロジェクトのプロパティで選択できるようになります。
ちなみに、ad-hocでudidを追加した場合でも、XCodeでダウンロードしなおす必要があります。
その際、Visual Studio側も再起動して、iOSプロジェクトのプロパティを再選択しないとダメっぽいです。
最後に、ad-hocのudid指定が正しくされているかの確認は、ipaファイルの拡張子をzipに変更して中を参照し、embedded.mobileprovisionというファイルを強引にテキストエディタで開いて、
<key>ProvisionedDevices</key>
の部分を参照すれば、OK
Xamarin.Forms Androidのストアへの公開方法
Xamarin.FormsでAndroidアプリのストアへの公開方法のメモです。
新しいキーストアを作ります。
Visual Studioのツールメニューから、[Android]-[Android Adb Command Prompt...]を選択。
コマンドプロンプトが起動するので、
keytool -genkey -v -keystore <パスを含んだファイル名> -alias <キーストア内のキーの名前> -keyalg RSA -keysize 2048 -validity 10000
を入力し、必要事項にこたえていきます。
Visual Studioのツールメニューから、[Android]-[Publish Android App...]を選択。
先ほど作成したKeyStore情報を入力します。
次の画面で、APKファイルの出力場所と名前を指定します。
基本的に初期値で良いでしょう。但し、APK パッケージ名は「com.example.myapp」形式で指定する必要があります。
ファイル名がこれに準拠していない場合は、DroidプロジェクトのプロパティでPackage nameを変更しましょう。
Xamarin.Formsでとりあえずスプラッシュ(起動)画面を表示
Xamarin.Formsのテンプレートを使用すると、iOSのResourcesにデフォルトのアイコンやスプラッシュ画面と思える画像が用意されている。当然、ファイル名がどこかに記述されているんだろうなとは思うものの、とりあえず、そのまま画像を変更しちゃえば変わるだろうなと試したところ変わらない・・・
僕だけじゃないよね?
いろいろ方法はありそうだけど、スプラッシュ画面なんてなんでも良いけど、デフォルトのXamarinロゴはさすがにってレベルだと、画像差し替えだけでなんとかしたいですよね(笑)
そんな人は、iOSプロジェクトのプロパティで、iOS Applicationタブにある、Launch Storyboard:という部分に入っている、LaunchScreenという文字を消してみましょう。
これで、シミュレータで確認する限り、だいたいのプラットフォームで変わるはず。
Xamarin.Formsで設定の読み書きをDependency Serviceを使用しないで行ってみる
Xamarin.Formsで設定の保存をGoogle先生に聞いてみると、一般的な手法(色々な人が解説してくれている)では、Dependency Serviceを使用するのが良さそうだと教えてくれます。
ただ、これはこれで良いけど、データとメソッドを一つのクラスにして、プラットフォーム別の差異を継承で処理しちゃっても良いんじゃね?
と思っちゃったので、ちょっと試してみました。
良い例題がパッと思い浮かばないので、そのままデータの保存で試してみます。
まずは、共通プロジェクトに設定情報を管理するクラスの抽象クラスを定義する。
[XFApp1\ASettingInfo.cs]
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace XFApp1 { public abstract class ASettingInfo { /// <summary>ユーザーID</summary> public string UserId { get; set; } /// <summary>ユーザー名</summary> public string UserName { get; set; } /// <summary>保存</summary> public abstract void Save(); /// <summary>読込</summary> public abstract void Read(); } }
そして、とりあえず共通プロジェクトのApp.csにstaticに宣言しちゃう!!
(なんでもかんでも、staticにしちゃダメよって言われそうですが・・・)
ついでに、テストに使用するテキストボックス(Entry)を2つと保存ボタンも定義して、
保存ボタンで入力値を保存して、プログラムの起動時に読み込む処理を記述しておきます。
[XFApp1\App.cs]
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Xamarin.Forms; namespace XFApp1 { public class App : Application { //設定情報保持用 public static ASettingInfo MySettingInfo = null; //コントロール private Entry txtUserId = new Entry(); private Entry txtUserName = new Entry(); private Button btSave = new Button(); public App() { // The root page of your application MainPage = new ContentPage { Content = new StackLayout { VerticalOptions = LayoutOptions.Center, Children = { new Label { HorizontalTextAlignment = TextAlignment.Center, Text = "Welcome to Xamarin Forms!" }, txtUserId, txtUserName, btSave } } }; //コントロールのプロパティを適当に・・・ txtUserId.Placeholder = "ユーザーID"; txtUserName.Placeholder = "ユーザー名"; btSave.Text = "保存"; btSave.Clicked += btSave_Clicked; } protected override void OnStart() { //設定を読み込む App.MySettingInfo.Read(); //読み込んだ情報をセット txtUserId.Text = App.MySettingInfo.UserId; txtUserName.Text = App.MySettingInfo.UserName; } private void btSave_Clicked(object sender, EventArgs e) { //入力情報を保存 App.MySettingInfo.UserId = txtUserId.Text; App.MySettingInfo.UserName = txtUserName.Text; App.MySettingInfo.Save(); } } }
次に、Droidプロジェクト側で、実際にインスタンスを作成するクラスを作成します。
内容としては、先ほどのASettingInfoを継承して、先ほどは抽象メソッドとしていた部分の実態を記述します。
※NuGetで、Newtonsoft.Jsonをインストールしておいて下さい。
[XFApp1.Droid\DependeSettingInfo.cs]
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Newtonsoft.Json; namespace XFApp1.Droid { public class DependeSettingInfo : XFApp1.ASettingInfo { private const string cFILE_NAME = "SettingInfo.json"; /// <summary>保存</summary> public override void Save() { var json = JsonConvert.SerializeObject(this); string FilePath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal) + "/" + cFILE_NAME; System.IO.File.WriteAllText(FilePath, json); } /// <summary>読込</summary> public override void Read() { string FilePath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal) + "/" + cFILE_NAME; string json = null; DependeSettingInfo RecvObj = null; if (System.IO.File.Exists(FilePath)) { json = System.IO.File.ReadAllText(FilePath); RecvObj = JsonConvert.DeserializeObject<DependeSettingInfo>(json); this.UserId = RecvObj.UserId; this.UserName = RecvObj.UserName; } } } }
そして、プログラムの開始時に、冒頭で宣言していたstatic変数にインスタンスをセットするようにしておきます。
[XFApp1.Droid\MainActivity.cs]
using System; using Android.App; using Android.Content.PM; using Android.Runtime; using Android.Views; using Android.Widget; using Android.OS; namespace XFApp1.Droid { [Activity(Label = "XFApp1.Droid", Icon = "@drawable/icon", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)] public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity { protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); global::Xamarin.Forms.Forms.Init(this, bundle); //設定操作クラスのインスタンスを生成 App.MySettingInfo = new DependeSettingInfo(); LoadApplication(new App()); } } }
これで、Droid側で設定の読み書きと参照を行う準備ができました。
早速試してみましょう(^^)/
初回起動時は、当然テキストボックスには何も表示されません。
ユーザーIDとユーザー名を入力して、保存ボタンをクリックしてから、プログラムを再起動すると、
期待していた通りに表示されました(*^o^*)
次は、iOS側の処理になりますが、先ほどのDependeSettingInfo.csはiOS側のプロジェクトでもそのまま動きます。
なので、Visual Studioの機能でリンクを貼ります。
iOSプロジェクトを右クリックして[追加]→[既存の項目]を選択
先ほどDroid側に追加したDependeSettingInfo.csを、リンクとして追加します。
※もちろんリンクとして追加しなければならないということはありませんよ。
そして、Droidの時と同じように、プログラムの開始時に、冒頭で宣言していたstatic変数にインスタンスをセットするようにしておきます。
[XFApp1.iOS\AppDelegate.cs]
using System; using System.Collections.Generic; using System.Linq; using Foundation; using UIKit; using XFApp1.Droid; namespace XFApp1.iOS { // 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 partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate { // // This method is invoked when the application has loaded and is ready to run. In this // method you should instantiate the window, load the UI into it and then make the window // visible. // // You have 17 seconds to return from this method, or iOS will terminate your application. // public override bool FinishedLaunching(UIApplication app, NSDictionary options) { global::Xamarin.Forms.Forms.Init(); //設定操作クラスのインスタンスを生成 App.MySettingInfo = new DependeSettingInfo(); LoadApplication(new App()); return base.FinishedLaunching(app, options); } } }
同じようにテストしてみると、期待通りに動作しますよね?
UWPの場合は、Droidで作成したクラスをそのまま使う訳にはいきませんが、同じように抽象クラスを継承して作って、UWPで動作するように実装して、プログラム起動時にインスタンスがセットされるようにすれば、動作するはずです。
ここに書いた方法は、Xamarinの技術ではないのであえて書かなくても皆わかっていることかもしれませんが、Xamarinをキーワードに探すとあまり出てこない気がしますし、Xamarin初心者にとっては、動きそうだけど動くのかな?という不安があったのも事実なので、後に続く人の参考になればと書いておきました。
汎用的に使用するメソッドとかであれば、もちろんDependency Serviceを使用した方が良いと思いますが、方法論の一つとして、これも検討の価値はあるのではないかと思います。
もしも問題等あればご指摘下さい。
AndroidのMasterDetailPageから、アプリケーションアイコンを消すには
これが、iOSやWPFの時には出てこないし、その左側にメニューのアイコンが表示されることもあり、消したいと思うケースがあると思う。
(Androidなら出すべきとかは、とりあえずおいておいて・・・)
その場合は、DroidプロジェクトのResourcesフォルダに、valuesフォルダを追加し、スタイル定義用のxmlファイル(ここでは、MyStyle.xml)を追加する。
<?xml version="1.0" encoding="utf-8" ?> <resources> <!-- <style name="CustomTheme" parent="android:Theme.Holo.Light"> --> <style name="CustomTheme"> <item name="android:icon">@android:color/transparent</item> </style> </resources>
あとは、MainActivity.csを開いて、ActivityAttributeにThemeを追加してあげることにより、表示されなくなります。
using System; using Android.App; using Android.Content.PM; using Android.Runtime; using Android.Views; using Android.Widget; using Android.OS; namespace XFApp1.Droid { [Activity(Label = "XFApp1.Droid", Icon = "@drawable/icon", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation, Theme = "@style/CustomTheme")] public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity { protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); global::Xamarin.Forms.Forms.Init(this, bundle); Microsoft.WindowsAzure.MobileServices.CurrentPlatform.Init(); LoadApplication(new App()); } } }
Microsoft.Azure.Mobile.Clientを追加すると
Xamarin.FormsでMicrosoft.Azure.Mobile.Clientを使用したくて現在はまり中(--)
まず、テンプレートで、Xamarin.Forms(UWP/Android/iOS)を選択して、
何度かリビルドしたりソリューションを再起動したりして、エラー一覧に警告も何も出ない状態にして、UWP/Android/iOS、それぞれデバッガー上で実行して正常に起動することを確認。
その後、ソリューションを右クリックして「ソリューションの NuGet パッケージの管理」を選択して、
全てのプロジェクトに「Microsoft.Azure.Mobile.Client」をインストールしてリビルドすると、
この時点でのエラーと警告はこんな感じ。
とりあえずこの時点で、AndroidとiOSをデバッグ実行すると、起動することは確認。
そして、Azureのポータルのクイックスタートで表示されたとおりに、MobileServiceClientのインスタンス作成コード(using も当然追加)を、App.csに追記する。
この状態で、再度AndroidとiOSをデバッグ実行すると、Androidは問題なく起動するが、iOS側はエラーが発生してしまう。
もちろん、警告は出ているのでここらにヒントがあるような気もしますが、単純に支持されたとおりに、AutoGenerateBindingRedirectsをtrueにしただけではダメそうですね。
2016/06/27追記
どなたか、解決方法ご存じの方いらっしゃいませんか?
facebookの「Japan Xamarin User Group(JXUG)」で下記のアドバイスをいただきました。ありがごうございます!!
Azureポータルのクイックスタートには、特にそのような記述はなさそうですが、どうやら、iOSのプロジェクト側では、MobileServiceClientのインスタンス作成前に、初期化処理が必要みたいです。
iOS側のプロジェクトのAppDelegate.csでAppクラスのインスタンス作成前に、
Microsoft.WindowsAzure.MobileServices.CurrentPlatform.Init();
の一行を追加したらとりあえず起動はできました。
無事、動作するのかは別問題ですが(笑)
ちなみに、起動は初期化処理を入れなくてもできますが、どうやらAndroid側にも同様の初期化処理が必要みたいです。