2011/08/03
HTML5 で作る iOS アプリ PhoneGap 前に勉強会の雑談で聞いた程度で実のところ知らないのだが、ちょっと調べてみる。

インストール

PhoneGap公式サイト 、もしくはGitからダウンロード。 自分は公式サイトからダウンロードしました。 最新のMacBook Airに入れたので、Lion + Xcode4 の環境でインストール。 PhoneGap PhoneGap は Xcode4 に未対応みたいですが、www ディレクトリの選択処理をすればとりあえずは動くようです。 PhoneGap ちなみに、以下のライブラリがインストールされるようです。 PhoneGap

プロジェクト作成

PhoneGap をインストール後の Xcode プロジェクト作成画面に、「PhoneGap」を選択できるようになります。 プロジェクトを作成すると、必要な Framework や テンプレートファイルも作成されています。 PhoneGap.framkework の中身は以下の通り。 PhoneGap JSON のように普通のライブラリや、Camrea のようにラッパー関数が入ってるものがあります。

www ディレクトリの設定

Xcode4 でインストールすると www ディレクトリがプロジェクト内に表示されないので、手動で選択する必要があります。 (1) File > Add File To "PhoneGap" を選択。 PhoneGap (2) www ディレクトリを選択は、 Copy items into ...のチェックを外し、Create Folder Reference をチェックして行う。 PhoneGap

PhoneGap の概要

説明の順が逆になってしまいましたが、PhoneGap の最大の特徴は

HTML ベースであってビューは HTML + CSS 、コントロールは JavaScript(JQuery Mobile)

にあるでしょう。 iOS よりに言うと UIWebView ベースで iPhone アプリが動いている事になります。 また、JQuery から PhoneGap.freamework を通じて、Objective-C のネイティブコードにアクセスできるようです。 ※ネイティブコードの呼び出しの仕組みは「PhoneGap: NativeCodeの呼び出し」を参考 以上を踏まえると、Titanium Mobile よりも一層 Web系開発に近く開発難易度が低いかも知れません。 ただ裏を返せば WebView ベースなので JQuery Mobile と WebKit の仕様にほぼ依存してしまう事がデメリットでしょう。

つまりは動作が遅くなったり、UIWebView による不具合の可能性を秘めています

また、ネイティブコードとの連携もグレーゾーンかもしれません(やってみないとわからない)。 しかし PhoneGap はハマれば、作業分担や開発効率の面では最強かも知れません。 (ただ、設計がとても重要になるでしょう) 電子書籍アプリ系で PhoneGap を選択する理由が何となくわかった気がします。

  2011/07/30
Macbook Air 13 が届いたので色々とインストール中。 MacPorts でなく Homebrew をインストールすることにした。

Hombebrew のインストール

Ruby でインストールします。

/usr/bin/ruby -e "$(curl -fsSL https://raw.github.com/gist/323731)"

デフォルトだとruby のパスは通ってないので、設定した方がいいですね。 ※2012/04/21現在は以下のコマンドに変更(?)

ruby -e "$(/usr/bin/curl -fksSL https://raw.github.com/mxcl/homebrew/master/Library/Contributions/install_homebrew.rb)"

パッケージ

Homebrew ではパッケージのことを Formula と言うそうです。 Formula を検索するには

brew search FormulaName

インストールするには

brew install FormulaName

だが、インストールで以下のエラーがでる。

Error: Cannot write to /usr/local

/usr/local の書き込み権限がない(root)になってるので、sudo するか 権限を変更するか?ですよね。 とりあえず、権限を変更してみる。

sudo chown -R $USER /usr/local

これで Formula をインストールできるようになりました。

コマンド

ヘルプコマンドがあるので、これでだいたいわかるかと。

brew help Example usage: brew install FORMULA... brew uninstall FORMULA... brew search [foo] brew list [FORMULA...] brew update brew outdated brew [info | home] [FORMULA...] Troubleshooting: brew doctor brew install -vd FORMULA brew [--env | --config] Brewing: brew create [URL [--no-fetch]] brew edit [FORMULA...] open https://github.com/mxcl/homebrew/wiki/Formula-Cookbook Further help: man brew brew home

  2011/07/24
AppStoreでアプリがアップデート公開されたら、とんでもない自体になりました。

バージョンアップしたらアプリが起動しない!

と恐ろしい報告が。。。 今回のアップデートはSQLite に 12 カラム追加したので恐らく CoreData あたりかな?と思うのですが、migrate の仕方も問題ないですし開発でもアップデートできているので・・・原因が掴めません。

アプリのログを確認する

まず、アプリのログを見たい!ってことで、どうすればいいのかと言うと、 (1) iPhone のアプリを iTunes 同期させる。 CoreData (2) 以下のディレクトリにクラッシュログが保存されている。

/Users/ユーザ/Library/Logs/App Store/CrashReporter

するとこんなログが

execution code が 0x8badf00d ("ate bad food")

これを元にググってみる。

CoreData のマイグレーションは時間がかかる

CoreData - マイグレーションを考慮した CoreDataManager パターン の記事で解決しました。 (まだAppStoreで公開されていないので、多分ですが・・・) CoreData に限らず

application:didFinishLaunchingWithOptions で制限時間を超えると起動しない

のです。 改めて前のバージョンの開発バージョンに戻して試した結果

データ200件超で、カラム12個追加で 30秒くらいでした

ということで、自分のアプリの対策をすることにしました。

マイグレーション判別の画面を追加

一番の肝は、didFinishLaunchingWithOptionsで マイグレーションの待機処理させない事です。 問題のアプリの構成は、

(1) UITabView で複数画面存在する (2) 最初の起動画面で CoreData にアクセスしての一覧表示 (3) 他の画面でも CoreData にアクセスする

シーケンス的には、

didFinishLaunchingWithOptions 起動 → UITabView 起動 → ViewController 起動 → マイグレーション判別と処理 ※非同期処理 → トップ画面表示

重要なのは、dispatch_async(GCD) のブロック文で非同期処理する事です。 でないと、didFinishLaunchingWithOptions で待機してしまい、また時間制限で終了してしまいます。 ということで、まずUITabView にマイグレーション処理する ViewController を追加。 CoreData CoreData ユーザにあまり違和感を与えないように、Top画面としました。 この辺は作るアプリによって違いますので、それぞれ考える必要がありますね。

マイグレーションを判別する

CoreData - マイグレーションを考慮した CoreDataManager パターン の記事では、CoreDataManager を別途作ってやっていますが、それをすると今回は修正が大変なので AppDelegate 経由で処理させることに。 ただし、あくまでも AppDelegate に 一般的な CoreData の処理が実装されている話が前提です。 まずは、マイグレーションを判別するコード
- (BOOL)isRequiredMigration {
	NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Sample.sqlite"];
	NSError* error = nil;
	
	NSDictionary* sourceMetaData = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:NSSQLiteStoreType
															   URL:storeURL
															 error:&error];
	if (sourceMetaData == nil) {
		return NO;
	} else if (error) {
		NSLog(@"Checking migration was failed (%@, %@)", error, [error userInfo]);
		abort();
	}
	
	BOOL isCompatible = [self.managedObjectModel isConfiguration:nil
										compatibleWithStoreMetadata:sourceMetaData]; 
	
	return !isCompatible;
}
isConfiguration:nil

マイグレーションの更新

マイグレーションの更新に関しては、従来通り persistentStoreCoordinator で処理すればいいけど、気分的に明示的に別途コードを追加。
- (NSPersistentStoreCoordinator *)doMigration {
    NSLog(@"--- doMigration ---");
	NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Sample.sqlite"];
	
	NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                             [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                             [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,
                             nil];
    NSError *error = nil;
    __persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error])
    {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }    
    
    return __persistentStoreCoordinator;
}
マイグレション更新という意味では、NSPersistentStoreCoordinator を返す必要はないので void か BOOL でよいかも。

マイグレーション実行画面を作る

UITabView で最初に起動される TopViewController とマイグレーション実行画面 MigrateViewController も作成。 CoreData マイグレーション TopViewController の ViewDidLoad にマイグレーション更新時に TopViewController を起動させる処理を記述。
- (void)viewDidLoad {
    [super viewDidLoad];
    SampleAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];

    if ([appDelegate isRequiredMigration]) {
        [self showMigrateView];
    }
}

- (void)showMigrateView {
    SampleAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
    MigrateViewController *controller = [[MigrateViewController alloc]
													initWithNibName:@"MigrateViewController"
													bundle:nil];
	
	controller.delegate = self;
	controller.view.alpha = 0.0f;
	[appDelegate.window addSubview:controller.view];
	
	[UIView animateWithDuration:0.5f
						  delay:0.0f
						options:UIViewAnimationOptionAllowUserInteraction
					 animations:^{
						 [controller.view setFrame:CGRectMake(0, 0, 320, 480)];
						 [controller.view setAlpha:1.0f];
					 }
					 completion:^(BOOL finished){
						 
					 }];
	
}
最後に、MigrateViewController が起動された時にマイグレーション更新処理をする。
- (void)doMigration {
        SampleAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
	[appDelegate doMigration];
}

- (void)viewWillAppear:(BOOL)animated {
	dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

	self.message.text = NSLocalizedString(@"MIGRATION_MESSAGE_UPDATE", nil);
	self.okButton.hidden = YES;
	self.indicator.hidden = NO;
	
	dispatch_async(queue, ^{[self doMigration];
		dispatch_async(dispatch_get_main_queue(), ^{
			self.message.text = NSLocalizedString(@"MIGRATION_MESSAGE_RESULT", nil);
			self.indicator.hidden = YES;
			self.okButton.hidden = NO;
		});
	});
	
}
これで、CoreData のマイグレーションが発生した場合は、非同期で更新処理がされるはずです。 いやぁ、本当に盲点でした。過信はいけませんねぇ。

  2011/07/18
info.plist に UIPrerenderedIcon を追加しチェックするとアイコンの光沢が消えます。 iphone アイコン XcodeのバージョンによってInfo.plistの設定UIが変わります。 4.6現在だと、TARGETS > Info で「Icon files」の階層内で設定してやります。

Icon already includes gloss effects

  2011/07/17
去年のクリスマスに買った Kinect の箱をようやく開けました・・・。 Open Kinect Projectで公開されているやつですね。 Getting Started とか MacBook Air で Xbox 360 Kinect してみる (Mac OS X with OpenKinect) を参考にやってみました。

MacPorts のインストール

MacPorts をインストールしていなければ、インストール。

$ sudo port selfupdate $ sudo port upgrade installed

git と cmake のインストール

$ sudo port install git-core $ sudo port install cmake

OpenKinect と libusb のダウンロード

$ git clone git://git.libusb.org/libusb.git $ git clone https://github.com/OpenKinect/libfreenect.git

libusb のインストール

$ cd ./libusb/ $ chmod +x autogen.sh $ ./autogen.sh $ patch -p1 < ../libfreenect/platform/osx/libusb-osx-kinect.diff $ ./configure $ make $ sudo make install | tee ./install.log

OpenKinect のインストール

Xcode のプロジェクトで作成する。 build ディレクトリを作成してインストールするとよい。

$ mkdir ./libfreenect/build $ cd ./libfreenect/build $ ccmake -G Xcode ..

kinect ccmake の画面では [c] で configure してから [g] で genarate する。 最後に、cmake して Xcode プロジェクト libfreenect.xcodeproj が作成される。

cmake -G Xcode ..

Xcode で実行

Kinect センサを接続して、作成した libfreenect.xcodeproj を起動する。 kinect いくつかサンプルがあるので選択して、【ビルドと実行】する。 hiview で実行した場合 kinect titdemo のサンプルは映像なしでカメラが上下に動いてびっくりしましたw 普通にmake install して起動した場合 kinect しかし、AS3 サーバとかあるんですねぇ。 Wrapper がこんなにあるので、将来的に楽しみです。 - Python - C Synchronous - Actionscript - C++ - C# - Java JNI - Java JNA - Javascript - Common Lisp 案外あっさり動きましたが、これからが大変そうだと思います・・・。

  2011/07/17
Rails3.0 のリリースに関してはRails 3.0 リリースノート和訳 - 前編で和訳されてます。 第2回: 新規アプリケーションの作成を参考にRails 3.0 を使ってみる。

新規アプリ作成

$ rails new rails_test $ cd rails_test $ ls -al -rw-r--r-- 1 yoo yoo 36 2011-07-17 00:38 .gitignore -rw-r--r-- 1 yoo yoo 743 2011-07-17 00:38 Gemfile -rw-r--r-- 1 yoo yoo 1660 2011-07-17 01:06 Gemfile.lock -rw-r--r-- 1 yoo yoo 9126 2011-07-17 00:38 README -rw-r--r-- 1 yoo yoo 269 2011-07-17 00:38 Rakefile drwxr-xr-x 7 yoo yoo 4096 2011-07-17 00:38 app drwxr-xr-x 5 yoo yoo 4096 2011-07-17 00:38 config -rw-r--r-- 1 yoo yoo 159 2011-07-17 00:38 config.ru drwxr-xr-x 2 yoo yoo 4096 2011-07-17 00:38 db drwxr-xr-x 2 yoo yoo 4096 2011-07-17 00:38 doc drwxr-xr-x 3 yoo yoo 4096 2011-07-17 00:38 lib drwxr-xr-x 2 yoo yoo 4096 2011-07-17 00:38 log drwxr-xr-x 5 yoo yoo 4096 2011-07-17 00:38 public drwxr-xr-x 2 yoo yoo 4096 2011-07-17 00:38 script drwxr-xr-x 7 yoo yoo 4096 2011-07-17 00:38 test drwxr-xr-x 6 yoo yoo 4096 2011-07-17 00:38 tmp drwxr-xr-x 3 yoo yoo 4096 2011-07-17 00:38 vendor

ここら辺ファイル構成は、MVCに慣れてれば問題ないでしょう。 次に、DBを設定してアプリを起動。

$ bundle install Fetching source index for http://rubygems.org/ Using rake (0.9.2) Using abstract (1.0.0) ... $ sudo gem instal sqlite3 $ rails server

ブラウザからポート3000 でアクセスする。 rails ちゃんとDB(Active Record)も有効になってます。 rails

コントローラ/ビューの作成

tasks コントローラと index アクションを指定して作成。

$ rails generate controller tasks index create app/controllers/tasks_controller.rb route get "tasks/index" invoke erb create app/views/tasks create app/views/tasks/index.html.erb invoke test_unit create test/functional/tasks_controller_test.rb invoke helper create app/helpers/tasks_helper.rb invoke test_unit create test/unit/helpers/tasks_helper_test.rb

config/routes.rb にURLアクセス制御の関数が記述されている。
RailsTest::Application.routes.draw do
  get "tasks/index"
end
この状態で http://host:3000/tasks/index でアクセスでき、
RailsTest::Application.routes.draw do
  resources :tasks, :only => [ :index ]
end
と書き換えると、index を除いた http://host:3000/tasks でアクセスできます。 これは便利!

ビューの基礎

ここら辺も他のフレームワークと同じなので説明はいらないとは思いますが、

個別のビュー:app/コントローラ名/ビューファイル.erb レイアウト:app/views/layouts/application.html.erb

を修正してやるだけです。 ちなみに「app/views/layouts/コントローラ名.html.erb」レイアウトファイルを作成すると優先して利用されます。 ※application.html.erb は Rails 3.0 で自動作成されるようになったそうです

ビューの部分テンプレート

app/views/ディレクトリ名/ にアンダースコアで始まるテンプレートを入れ、読み込んでやるとパーツのテンプレートが利用できます。 app/views/_footer.html.erb を作成して、テンプレートファイルで読み込み。

<%= render 'ディレクトリ名/footer' %>

  2011/07/16
最近 Ruby 信者が更に増えてる気がする。 数年前にちょっとさわったくらいで、実際 Ruby でシステム作った事がない! という事で、今更ながら Ruby on Rails 入門

Rubyインストール

Debian(Lenny) で構築しました。

# aptitude update # aptitude safe-upgrade # aptitude install libssl-dev zlib1g-dev libreadline6-dev # aptitude install libsqlite3-dev # aptitude install ruby # aptitude install ruby1.9.1 # aptitude install ruby1.9.1-dev # ruby -v ruby 1.8.7 (2010-08-16 patchlevel 302) [i486-linux]

ruby でインストールすると 1.8.7 になったので、切り替え設定をする。 # update-alternatives --install /usr/bin/ruby ruby /usr/bin/ruby1.8 0 # update-alternatives --install /usr/bin/ruby ruby /usr/bin/ruby1.9.1 1

選択肢 パス 優先度 状態 ------------------------------------------------------------ * 0 /usr/bin/ruby1.9.1 1 自動モード 1 /usr/bin/ruby1.8 0 手動モード 2 /usr/bin/ruby1.9.1 1 手動モード 現在の選択 [*] を保持するには Enter、さもなければ選択肢の番号のキーを押してください: 0 # ruby -v ruby 1.9.2p0 (2010-08-18 revision 29036) [i486-linux]

gems、rails のインストール

次に、Rails を gemでインストール。 ※gem install は反応が遅いのと、時間がかかります

# aptitude install rubygems # gem install rubygems-update Successfully installed rubygems-update-1.8.5 # gem install tzinfo builder memcache-client rack rack-test rack-mount erubis mail text-format thor bundler i18n # gem install rails ... Successfully installed railties-3.0.9 Successfully installed rails-3.0.9 11 gems installed ...

インストールすると途中でエラー??

File not found: lib

gem のパッケージ一覧を確認

# gem list ... rack-test (0.6.0, 0.5.7) rails (3.0.9, 3.0.0) railties (3.0.9, 3.0.0) rake (0.9.2) ...

うーん、インストールされている。

# gem which rails /var/lib/gems/1.8/gems/railties-3.0.9/lib/rails.rb

しかし、rails のパスが通っていなかったり、‘File not found: lib’ エラーがでる。

rdocインストール・libディレクトリの生成

‘File not found: lib’の問題は、gem install railsでFile not found: libを参照。 どうやら1.8系ではなく1.9系だとこのエラーがでるようだ(?)。

# cd var/lib/gems/1.8/gems # gem install rdoc-data # gem rdoc --all --overwrite # cd /var/lib/gems/1.8/gems/rails-3.0.9 # mkdir lib # gem rails install

rails のパスを通す

色んなサイトを見てると何もせずに rails のパスが通ってるみたいだけど、.bashに手動で通す。 (sudo でやらなかったから?だと思う)

$ vi ~/.bashrc export GEM_HOME=/var/lib/gems/1.8/ export PATH=$PATH:/var/lib/gems/1.8/bin export RUBYLIB=$RUBYLIB:/var/lib/gems/1.8/lib $ rails -v Rails 3.0.9

何かしらエラーがでたら「RailsエラーQA - Ruby」が参考になるかも。

  2011/07/12
dispatchKeyEvent をオーバライドすることで、キーイベントを取得できる。 これを利用して、KeyEvent.KEYCODE_BAK (戻るボタンフラグ)を判別して、 親クラスの dispatchKeyEvent をさせなければよいみたいだ。

戻るボタンを無効にする

[java] @Override public boolean dispatchKeyEvent(KeyEvent event) { if (event.getAction() == KeyEvent.ACTION_DOWN) { if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) { return true; } } return super.dispatchKeyEvent(event); } [/java]

  2011/07/11

Manifestファイルに追加


    <uses-permission android:name="android.permission.WAKE_LOCK" >
    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" >

KeyguardManager、KeyguardLock を利用する

Context から KeyguardManager を取得し KeyguardManager.KeyguardLock でスクリーンロックをはずします。 KeyguardManager.OnKeyguardExitResult ハンドラが呼ばれると PowerManager.WakeLock でスクリーンスリープから復帰します。 [java] protected WakeLock wakelock; protected KeyguardManager keyguardmanager; protected KeyguardLock keyguardlock; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.alarm); final Context _context = this.getApplicationContext(); keyguardmanager = (KeyguardManager) _context.getSystemService(Context.KEYGUARD_SERVICE); keyguardlock = keyguardmanager.newKeyguardLock("FindMyPhone"); keyguardlock.disableKeyguard(); keyguardmanager.exitKeyguardSecurely(new OnKeyguardExitResult() { public void onKeyguardExitResult(boolean success) { wakelock = ((PowerManager) _context.getSystemService(Context.POWER_SERVICE)) .newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "FindMyPhone"); wakelock.acquire(); } }); } @Override public void onDestroy() { super.onDestroy(); if (wakelock != null && wakelock.isHeld()) { wakelock.release(); } if (keyguardlock != null) { keyguardlock.reenableKeyguard(); } } [/java] onDestroy() のライフサイクルでキーロックと スクリーンを戻してますが、ちょっと疑問です。 アプリの仕様にもよると思いますが、スクリーンロックは最初の状態にちゃんと戻さないと、予期しない問題が起こるとの事です。

  2011/07/07

画像ファイルの用意

まず、toggle_button_on.png、toggle_button_off.png ファイルをそれぞれ作成し、drawable に入れる。

xml ファイルの定義

drawable/toggle_button.xml を作成し、state_checked をそれぞれ設定する。

<?xml version="1.0" encoding="UTF-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
	<item
		android:state_checked="true"
		android:drawable="@drawable/toggle_button_on" >
	<item
		android:state_checked="false"
		android:drawable="@drawable/toggle_button_off" >
</selector>

layout の設定

layout xmlファイルで ToggleButton の background に toggle_button.xml を設定する。

            <ToggleButton 
            	android:id="@+id/activeButton" 
            	android:text="" 
            	android:textOn=""
            	android:textOff=""
            	android:background="@drawable/toggle_button"
            	android:layout_width="wrap_content" 
            	android:layout_height="wrap_content"
            	android:layout_marginLeft="10dip"
            	>
Cloud9 を起動する -初心者編-
gcloud で GCEインスタンスを起動してみる
AWS CLI と jq でインスタンス一覧を整形して表示
React と Laravel7 のプロジェクトを作成する
Homebrewインストール-2020年版
3直線で囲まれた範囲塗りつぶし
PuLP で線形最適化問題を解く
カスタムのペジネーションを作る
node-sass を使って sass をコンパイルする
Log ファサードでSQLログを分離して書き出す
いちから始める Docker - 複数のコンテナを使う - (2020年)
いちから始める Docker - docker-compose を使う - (2020年)
AWS ECR を使ってみる
Laravel7 でマルチ認証
Mac に AWS Client を設定する
Laravel 7 リリース
v-html でHTML表示する
Laravel で Vue コンポーネントを使う
Laravel で Nuxt.js を使ってみる(Docker環境)
いちから始める Docker -コンテナをビルド- (2020年)
いちから始める Docker -起動してみる- (2020年)
Mac で MySQL(8系)
composer で vendor がインストールできない
Eloquent の日付を Carbon で扱う
webpack 4 入門(npm編)
[Mac]容量を減らす
DIコンテナはじめ
freee SDKを Laravel で使ってみる
freee API を使ってみる
Segueを利用しない画面遷移
Xcode11.3 で XVim2 を利用する
Codable で JSONを読み込み
Webpack入門(yarn編)
MacからLaradock PostgreSQLで接続エラー
Dockerで不要なコンテナ・イメージを削除
Mac で Laradock の構築
Composer インストール
yarn インストール&プロジェクト作成
Laravel 6.x 構築(Homestead編)
nvm インストール
npm install が Mac でエラー
HTMLタグでカーソルが同時処理(ミラーリング)されてしまう
DI(依存性注入)
[Ubuntu]Let's Encryptで無料の証明書を利用する
[Apache]Apache2.4のアクセス制限が変更
[Ubuntu]rootのログインとsudo権限追加
タミヤ マイコンロボット工作セットをMacに接続してみた
pgAdimn4 でブラウザで開けなくなる
Java8 を HomebrewとjEnvで構築
Android Studio環境構築 2019