Amazonアソシエイト
ブログ始めて1週間経ったところでAmazonアソシエイトに申し込んで、
無事審査に合格しました
- 記事は20くらい
- 日々のアクセスはほぼ0
・・・多分、長年アマゾンプライム会員だったからかな。。
運用方法はオーソドックスに
- サイドバーにウィジェット
- オススメ商品は記事内
でとりあえずやってみます。。てかそれ以外思いつきません。。
【C#】DataContractJsonSerializerでJSONを扱う
使用するための準備
1. シリアライズ(Object > JSON)用メソッドを作成
using System.IO; // ←追加 using System.Runtime.Serialization.Json; // ←追加 namespace JsonTestApp { public static class JsonUtils { /// <summary> /// オブジェクトからJSONへ変換します /// </summary> /// <param name="obj">JSONへ変換するオブジェクト</param> /// <returns>JSON</returns> public static string ToJson(object obj) { using (MemoryStream ms = new MemoryStream()) { var serializer = new DataContractJsonSerializer(obj.GetType()); serializer.WriteObject(ms, obj); return Encoding.UTF8.GetString(ms.ToArray()); } } } }
2. デシリアライズ(JSON > Object)用メソッドを作成
using System.IO; // ←追加 using System.Runtime.Serialization.Json; // ←追加 namespace JsonTestApp { public static class JsonUtils { /// <summary> /// JSONからオブジェクトへ変換します /// </summary> /// <typeparam name="T"></typeparam> /// <param name="json">オブジェクトへ変換するJSON</param> /// <returns>オブジェクト</returns> public static T ToObject<T>(string json) { using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(json))) { var serializer = new DataContractJsonSerializer(typeof(T)); return (T)serializer.ReadObject(ms); } } } }
実際の使用例
1. JSONへ変換するためのオブジェクトを作成
using System.Runtime.Serialization; // ←追加 namespace JsonTestApp { [DataContract] // ←重要 class SampleData { [DataMember] // ←重要 public string name { get; set; } [DataMember] // ←重要 public string age { get; set; } } }
2. Object から JSONへ
static void Main(string[] args) { SampleData data = new SampleData(); data.name = "大泉 洋"; data.age = "44歳"; string json = JsonUtils.ToJson(data); Console.WriteLine(json); }
コンソール出力結果
"{\"age\":\"44歳\",\"name\":\"大泉 洋\"}"
3. JSONからObjectへ
static void Main(string[] args) { string json = "{\"age\":\"44歳\",\"name\":\"大泉 洋\"}"; SampleData data = JsonUtils.ToObject<SampleData>(json); Console.WriteLine(data.name); Console.WriteLine(data.age); }
コンソール出力結果
大泉 洋 44歳
【XAMARIN】ピッカーの初期値
ピッカーの初期値を設定したくて悩んだ話
まず、以下のようにピッカーを準備
XAML
<Picker x:Name="picker" ItemDisplayBinding="{Binding Key}"/>
C#
ピッカー用のモデルクラス
using System; namespace SimpleMemo { public class PickerModel { public int Id { get; set; } public string Key { get; set; } } }
ピッカーの中身を設定
// ピッカー用のリスト ObservableCollection<PickerModel> Lists = new ObservableCollection<PickerModel>(); // ピッカーの中身をDBから取得 foreach (var row in db.Table<CategoryTable>().OrderBy(X => X.Id).ToList()) { Lists.Add(new PickerModel { Id = row.Id, Key = row.Key }); } // ピッカーソース設定 this.picker.ItemsSource = this.Lists;
で、画面表示時にピッカーの初期値を設定したくて、悩んだ結果、以下のようにしました。
// ピッカー用のリストから、Id = 2のもののIndexを取得 var idx = this.Lists.Select((item, index) => new { Index = index, Value = item }) .Where(item => item.Value.Id == 2) .Select(item => item.Index); // ピッカーの初期インデックスを設定 this.picker.SelectedIndex = idx.Single();
他に良い方法があれば、教えてください。。
【XAMARIN】SQLiteを試す
データの永続的な保存方法として、SQLiteを使用してみた。
<注意>自分は今回以下のように使用しただけで、本当に使い方が合ってるかは分かりかねます
使用準備
NuGetから「sqlite-net-pcl」をインポートするだけ
テーブル用のクラスを作成
using System; namespace SimpleMemo { public class CategoryTable { [SQLite.PrimaryKey, SQLite.AutoIncrement] public int Id { get; set; } public string Key { get; set; } } }
CategoryTable というテーブルを作成。
[Id]というカラムをプライマリキーにし、自動採番するようにしてます。
SELECT
string database = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "SimpleMemo.db"); using (var db = new SQLite.SQLiteConnection(database) { // テーブル作成(何度呼び出しても問題なし。すでに作成されている場合はCreateTableは走らないらしい) db.CreateTable<CategoryTable>(); // カテゴリテーブルのデータを全て取得(ID順) List<CategoryTable> row = db.Table<CategoryTable>().OrderBy(x => x.Id).ToList(); }
UPDATE
using (var db = new SQLite.SQLiteConnection(database) { // Id = 1のレコードを取得 CategoryTable row = db.Table<CategoryTable>().SingleOrDefault(x => x.Id == 1); // 更新 if (row != null) { row.Key = "ざまりん"; db.Update(row); } }
直にUPDATE文を書いた方がSQL一回で済むし、処理的には速そう
DELETE
using (var db = new SQLite.SQLiteConnection(database) { // Id = 1のレコードを取得 CategoryTable row = db.Table<CategoryTable>().SingleOrDefault(x => x.Id == 1); // 削除 if (row != null) { db.Delete<CategoryTable>(row.Id); } }
このやり方が良いのかは凄く微妙・・・
INSERT
using (var db = new SQLite.SQLiteConnection(database) { // 追加 db.Insert(new CategoryTable { Key = "ざまりん" }); }
ここで凄く悩んだことが一つ!!
INSERTで自動採番したIDを取得したいと思ったのですが、良い方法が見つからず。。。
結局、INSERT後に、以下のSQLを実行して取得してます。
// 一番新しい行を取得 CategoryTable lastData = db.Query<CategoryTable>("SELECT * FROM CategoryTable ORDER BY rowid desc limit 1").Single(); // ID取得 int id = lastData.Id;
もっと良い方法があるはず!!
どなたか教えていただけると嬉しいです。。。
【XAMARIN】Admob広告を表示
Xamarinを試してみるに、初めにAdmobの広告を試してみた。
実装方法は以下の方の記事が凄く参考になると思います。
qiita.com
手を入れたのは、iOSとAndroidのそれぞれのカスタムレンダラー。
Admobは自分で広告をクリックするとダメらしいので、
自分の端末をテスト端末として登録。
iOS
using System; using Xamarin.Forms; using Xamarin.Forms.Platform.iOS; using Google.MobileAds; using UIKit; using CoreGraphics; using SimpleMemo; using SimpleMemo.iOS; [assembly: ExportRenderer(typeof(AdMobBanner), typeof(AdMobBannerRenderer))] namespace SimpleMemo.iOS { public class AdMobBannerRenderer : ViewRenderer { private const string adUnitID = @"ca-app-pub-*********************"; // ← Admobで作成した広告ID private bool onScreen; protected override void OnElementChanged(ElementChangedEventArgs<View> e) { base.OnElementChanged(e); if (e.NewElement == null) { return; } if (e.OldElement == null) { UIViewController viewController = null; foreach (UIWindow window in UIApplication.SharedApplication.Windows) { if (window.RootViewController != null) { viewController = window.RootViewController; break; } } if (viewController == null) { viewController = UIApplication.SharedApplication.KeyWindow.RootViewController; } var banner = new BannerView(AdSizeCons.Banner, new CGPoint(-10, 0)) { AdUnitID = adUnitID, RootViewController = viewController }; banner.AdReceived += (sender, args) => { if (!onScreen) { AddSubview(banner); onScreen = true; } }; var request = Request.GetDefaultRequest(); request.TestDevices = new string[] { "*******************" }; // ← テスト端末のID banner.LoadRequest(request); SetNativeControl(banner); } } } }
Android
using System; using Xamarin.Forms; using Xamarin.Forms.Platform.Android; using SimpleMemo; using SimpleMemo.Droid; [assembly: ExportRenderer(typeof(AdMobBanner), typeof(AdMobBannerRenderer))] namespace SimpleMemo.Droid { public class AdMobBannerRenderer : ViewRenderer<AdMobBanner, Android.Gms.Ads.AdView> { private const string adUnitID = @"ca-app-pub-******************"; // ← Admobで作成した広告ID protected override void OnElementChanged(ElementChangedEventArgs<AdMobBanner> e) { base.OnElementChanged(e); if (Control == null) { var banner = new Android.Gms.Ads.AdView(Forms.Context); banner.AdSize = Android.Gms.Ads.AdSize.Banner; banner.AdUnitId = adUnitID; var builder = new Android.Gms.Ads.AdRequest.Builder(); builder.AddTestDevice("**************"); // ← テスト端末のID banner.LoadAd(builder.Build()); SetNativeControl(banner); } } } }
最後に、ちょっと困った?こと
最初、上記を実装しても全然広告が出ませんでした。
コンソールを見ると以下のような出力が。。。
There was a problem getting an ad response. ErrorCode: 0 Failed to load ad:0
これじゃ意味わからん!って困ってたのですが、単純なミスに気づく。。
Admobのアカウントを作成しただけで満足してて、必要なアカウント情報を入力してなかった・・・
アカウント情報を入力して、承認のメールが届いたら、表示されるようになりました。
以下、アカウントが承認された状態
ここが最初、「まだ完了してません」みたいなメッセージが出てました。。
【C#】インスタンスの動的生成(Type.Invokember)
※ TestClassというクラスは事前に作成しておく。
文字列からインスタンスを生成(動的にインスタンスを生成するのに便利)
string[] weekDays = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; // NameSpaceという名前空間のTestClassのインスタンスを生成(コンストラクタの引数にweekDaysを指定) Type t = Type.GetType("NameSpace.TestClass"); var inst = (TestClass)t.InvokeMember(null, System.Reflection.BindingFlags.CreateInstance, null, null, new object[] { weekDays });
インスタンスを指定してメソッドを実行(クラス違いの同名メソッドを実行するのに便利)
string[] weekDays = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; // TestClassのexecuteというメソッドを実行(メソッドの引数にweekDaysを指定) TestClass inst = new TestClass(); Type t = inst.GetType(); t.InvokeMember("execute", System.Reflection.BindingFlags.InvokeMethod, null, inst, new object[] { weekDays });
【C#】Windowsでの tail -f 的なことをしたかった
ので、簡易的なものを作ってみた
string file = "c:\aaa.txt"; FileInfo fi = new FileInfo(file); if (!fi.Exists) { Console.WriteLine(string.Format("指定されたファイル({0})が存在しません", file)); } using (FileStream fs = fi.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { bool run = true; // リードポインタをファイル最後尾にもってくる fs.Position = fs.Length; using (FileSystemWatcher fw = new FileSystemWatcher()) { // 監視するフォルダ fw.Path = fi.DirectoryName; // 監視フィルタ設定 fw.Filter = fi.Name; // 出力イベント用メソッド Action<Object, FileSystemEventArgs> ReadText = (sender, e) => { fi.Refresh(); // ファイルの追加分を読み込む long diff = fs.Length - fs.Position; if (diff < 1) { return; } byte[] bytes = new byte[diff]; fs.Read(bytes, 0, bytes.Length); // 読み込んだ文字列を行区切りに分割する string[] lines = Encoding.GetEncoding("utf-8").GetString(bytes).Split('\n'); // コンソールに出力 foreach (string line in lines) { if (!line.Equals("\r")) { Console.WriteLine(line); } } }; // 停止イベント用メソッド Action<Object, ConsoleCancelEventArgs> EventStop = (sender, e) => { // ウォッチ停止 fw.EnableRaisingEvents = false; }; // ctrl + c 時処理 Console.CancelKeyPress += new ConsoleCancelEventHandler(EventStop); // イベント検出時処理 fw.Changed += new FileSystemEventHandler(ReadText); // ウォッチ開始 fw.EnableRaisingEvents = true; // ループ処理 while (run) { string input = Console.ReadLine(); if (!string.IsNullOrEmpty(input) && input.Equals("quit")) { fw.EnableRaisingEvents = false; run = false; } } } } Console.WriteLine("\n\nStopped...");
aaa.txtに行が追加されると、自動でコンソールに出力される。
終了する場合には、"quit"と入力する。