2016/04/14

ThinkPad X1 Carbon(2016) 購入しました

ThinkPad X1 Carbon(2016)を購入しました。参考までに、これまで使っていたThinkPad X201sとSSDの読み込み速度を比較します。


構成
  • インテル Core i7-6600U プロセッサー (2.60GHz, 4MB)
  • 16GB LPDDR3 1866MHz (オンボード)
  • SSD 512GB PCIe-NVMe

・左:SSD(SSD 512GB PCIe-NVMe)[ThinkPad X1 Carbon(2016)]
・右:SSD(インテル335 Series SSD 240GB)[ThinkPad X201s]


読み込み書き込み共に非常に早くなっていますが、遅い部分もあるようです(*)。
ちなみに、今だと+32,400円で1TBが選択できるようになったようなので、容量に不安がある方には選択肢が増えたのは良いですね。私はThinkPad X201sから使用している外付けポータブルHDDを併用していこうと思っています。

重さもThinkPad X201sと同じぐらいで、画面サイズが大きく厚みが薄くなっているので使いやすいです。

スペックも上がったので非常に快適に使えています。


(*)CrystalDiskMarkのバージョンが違いますがどの程度影響があるかは分かりません。



また、ThinkPad WiGig ドックを購入しました。使ってみると無線でモニタに接続できるので非常に楽です。ただし、起動時やスタンバイ状態でのファンの音がします。特にスタンバイ状態でのファンの音は気になるので、場合によっては電源を切ったほうが良いのかもしれません。が、その運用で良いのかどうか・・・。


そのほか、Lenovo 65W トラベル AC アダプターも同時に注文しましたが、4週間以上で出荷となっていました。実際には1週間で到着したので気になるけど出荷日数で躊躇している方は考慮してみるといいかもしれません。


リカバリディスクの作成には16GBのUSBメモリを事前に用意しておくと良いです。私は用意していなかったので慌ててAmazonで注文しました。

前の関連記事:



2016/02/16

AutoHotkeyを使った効率的なカーソル操作ができるキーバインド

以前から記事にしようと思っていた効率的なカーソル操作ができるキーバインドのネタをようやく公開。
プログラムを書くプログラマーだけでなく、文章を書く人にも便利かもしれません。


さて、このキーバインドの考え方としては、
  • オンラインゲームでのWASDキーによる移動
  • viのカーソル移動
  • viによるモードの切り替え
を着想としています。

 基本的な考え方は3つです。
  •  Ctrlを押しながらキーを押すと、カーソルの操作ができる(カーソルを"コントロール"するイメージ)
  • さらにShiftを押すと、文字列を選択できる
  • Ctrl + Alt (+ Shift) を押しながらキーを押すと、削除できる

カーソルの移動は、ijkl です。それに加え、u と o を加えます。
Ctrl + i  (上)
Ctrl + j  (左)
Ctrl + k (下)
Ctrl + l  (右)

Ctrl + u  (行頭へ)
Ctrl + o  (行末へ)

この組み合わせに、Shift 及び Alt を追加すれば快適なカーソル操作ができるようになります。

無変換キーに半角/全角キーを登録するとさらに快適です。


今回は AutoHotkey のスクリプトにて最終的なものを紹介しますが、 お使いのソフトに登録してみてください。

実行環境

Windows7
AutoHotkey: v 1.0.48.03(Revision 30 - May 31, 2009)
日本語キーボード

AutoHotkeyはこちらからダウンロードします。最新のものをダウンロードすることをお勧めします。

https://autohotkey.com/




"keyboard.ahk"

/**
 * キーバインド
 *
 * "^" = Ctrl
 * "!" = Alt
 * "+" = Shift
 */

SendMode Event
;SendMode Play
;SendMode Input
;SendMode InputThenPlay

; 十字キーの移動(Ctrl + キー)
^i::Send {UP}
^j::Send {LEFT} ;←キーを割り当て
^l::Send {RIGHT}
^k::Send {DOWN} ;↓キーを割り当て
^u::Send {HOME}
^o::Send {END}

; 十字キーの選択移動(Ctrl + Shift + キー)
^+i::Send +{UP}
^+j::Send +{LEFT} ;←キーを割り当て
^+l::Send +{RIGHT}
^+k::Send +{DOWN} ;↓キーを割り当て
^+u::Send +{HOME}
^+o::Send +{END}


; eclipse;うまくいかないのでeclipse側でコマンドを変更することにした
;^+!o::Send ^+o
;return


; 削除(Ctrl + Alt (+ Shift) + キー)
^!l::
KeyWait Alt ;Altキーを離すまで実行されないようにすることで問題を回避
Send {DEL} ;Ctrl+Alt+Deleteとなりタスクマネージャが起動してしまう
return
^!j::Send {BS} ;Backspace
^!+l::Send {DEL} ;削除
^!+j::Send {BS} ;Shift + Backspace では動かないので{BS}のみ

; 無変換
sc07B::vkF3sc029 ;半角/全角

; カタカナ ひらがな
sc079::Send {BS}

; Ctrl + n
^n::Send {F2} ;名前の変更 


AutoHotkeyのバージョンが古いので、新しいバージョン(1.1.23.01)では、上記コード内に記述しているeclipseや削除部分での問題は解決しているかもしれません。
2010年当時には、参考にした日本語サイトが閉鎖したのでAutoHotkeyはもう更新されないと思っていたのですが、まだ開発を続けているみたいですね。

上記コードでは、カタカナ ひらがなキーを Back Space に置き換えていますが日常で使っていませんでした。同じようにCtrl + n で名前の変更できるようにしていましたが、こちらも使用していなかったのですが、今後活用してみようと思います。


最後に、このキーバインドに慣れると、他の人のPCを操作するときに不便に感じることがありますので、用法をお確かめの上ご利用ください。

ThinkPadのトラックポイントと組み合わせるとさらに効果的です。







2016/01/28

VBAで MSHTML.HTMLDocument を使うとCookieに関する Windows セキュリティの警告が出るようになった

2015年10月末ぐらいまでは特に問題なかったのですが、最近、VBAで MSHTML.HTMLDocument の createDocumentFromUrl を使うとCookieに関する Windows セキュリティの警告が出るようになりました。





調べてみると、2015年11月に配信されたWindowsUpdateによる影響の可能性が高そうです。
(参考:Internet Exploere(IE)を起動したらセキュリティ警告が表示された。

IEの設定で解除できるかと調べてみましたが見つけられなかったので、VBAの方で警告を表示しない方法で解決することにしました。


Sub GetHtml(ByVal url As String, Optional ByVal forceSecurityAlert As Boolean = True)
    Dim oHTML As MSHTML.HTMLDocument
    Dim doc As MSHTML.HTMLDocument
    Dim url As String
        
    If (oHTML Is Nothing) Then Set oHTML = New MSHTML.HTMLDocument
    
    ' セキュリティ警告を抑止する
    If forceSecurityAlert Then
        'oHTML.designMode = "on"
    End If
    
    Set doc = oHTML.createDocumentFromUrl(url, vbNullString)
 
    Do
        DoEvents
        If (doc.readyState = "complete") Then
            Exit Do
        End If
    Loop While (True)

    ' 以下、必要な処理
End Sub

大事な部分はこの部分です。

'セキュリティ警告を抑止する
If forceSecurityAlert Then
    'oHTML.designMode = "on"
End If


環境を以下の通りです。
Windows 7, Excel 2013, IE 11

参考にしたサイト




2015/05/13

SCOUT実行時の"ArgumentError: Error #3214"エラーの対処法

SCOUTをインストールして、プロジェクトを作成し、△ボタンを押して実行した際に "ArgumentError: Error #3214" というエラーが発生しました。

△ボタンを押して実行した際のエラー画面

原因としては、実行時にJavaを使用しており、そのパスが誤っているために起動できないためでした(開発環境は Windows 7 64bit)。

C:\Program Files (x86)\Scout\javascripts\app\process_interaction.js


function javaDir() {
  if(air.Capabilities.os.match(/Windows/)) {
    path = air.File.applicationDirectory.resolvePath("C:\\Program Files\\Java\\jre7\\bin\\java.exe");
    if(!path.exists){
      path = air.File.applicationDirectory.resolvePath("C:\\Program Files (x86)\\Java\\jre7\\bin\\java.exe");
      if(!path.exists){
        path = air.File.applicationDirectory.resolvePath("C:\\Program Files\\Java\\jre6\\bin\\java.exe");
      }
    }
    return path;
  } else {
    return air.File.applicationDirectory.resolvePath("/usr/bin/java");
  }
}

私の環境ではJre7がなくなっていたため、パスを上記の"Jre7"の部分を"jre1.8.0_31"に変更しました。
これで無事で実行することができました。

ファイルを編集するには管理者権限が必要です。

参考にしたサイト

・Getting "ArgumentError: Error #3214" #187
https://github.com/mhs/scout-app/issues/187

2014/06/22

Developing a Turn-based Multiplayer Game in Androidの翻訳(途中)

Google Play Game Services — Google Developers
の翻訳です。未完ですが、眠らせておくのももったいないので公開します。

 重要:Play Games services APIは、Google Play servicesのための簡略化したGoogle APIクライアントプログラミングモデルをサポートするように改訂されました。以前のGames clientは2014/02/07から非推奨になりました。既存または新規の開発者は 非推奨の GamesClient(リンクはない模様) に代わりに GoogleApiClientを使用することを強く推奨します。

このガイドは、Androidアプリにおける、Play Games services を使用したターンベースマルチプレイヤーゲームを実装する方法を示します。

はじめる前に

まだ(開発を)行っていない場合、turn-based multiplayer game concepts を見ると参考になるかもしれません。

ターンベースマルチプレイヤーゲームのコードを書く前に:
  • Google Play Developer Console内で、ゲームがターンベースのマルチプレイヤーサポートを有効になっていることを確認してください。
  • ダウンロードページより、ターンベースのマルチプレイヤーゲームのサンプルコードをダウンロードしレビューしてください。
  • ゲーム開発を簡単にするために、Accessing the Game APIsに説明しているように、メインゲームのActivityをBaseGameActivityクラスのサブクラスにすることができる。BaseGameActivityクラスはGoogleApiClient 接続とユーザーログインを操作するラッパーを提供しています。
  • Implementing Sign-In in Androidに説明しているガイドラインを参照するとよいでしょう。
一度、プレイヤーがログインし GoogleApiClientに接続したら、ゲームはターンベースのマルチプレイヤーAPIを使用することができます。

マッチを始める

ターンベースのマッチを始めるには、ゲームは、他の参加者と試合したい相手を指定する方法や、いくつかの規定した基準を使用した試合を構築した方法を選択することをプレイヤーに促すことができます。Play Games servicesは、ゲームにターンベースマッチのオブジェクトを返すためにゲームからマッチコンフィギュレーションデータを使用しています。このオブジェクトは、ターンベースマッチのライフサイクル上の全ての参加者と非同期に更新・共有されます。

試合を始めるには、これらのステップに従います:
  1. アプリ内で、プレイヤーがプレイしたいターンベースマッチの種類の詳細を収集し、試合に参加することができます。
    • ゲームは、SDKが提供する内蔵のプレイヤー選択ユーザーインターフェース(UI)を表示したり、このデータを収集するために独自のカスタムUIを使用することができます。プレイヤー選択UIの使用方法を学ぶには、デフォルトユーザーインターフェースによるプレイヤー選択を参照してください。
    • 別の方法として、ユーザーがプレイヤー選択UIを避けられるようにクイックスタートボタンを実装することができ、いくつかの規定した基準を使用して試合を構築する代わりになります。
  2. TurnBasedConfigObject内のマッチコンフィギュレーションデータを設定するTurnBasedMatchConfig.Builderを使用します。
  3. createMatch() を呼び、生成したTurnBasedConfigObjectを通します。自動マッチングが指定されている場合は、Play Games servicesは既存のゲームにマッチしようとします。詳細は、自動マッチングを実装を参照してください。
ターンベースマッチを生成するにあたり、ゲームはこれらのメソッドを呼ぶことができます:

-->
メソッド詳細
getSelectOpponentsIntent()オプション。デフォルトのプレーヤー選択UIを起動するためのインテントを返します。このUIから、ユーザーはランダムなGoogle+のユーザーと自動マッチする要求したり、他のGoogle+ユーザーをマッチするユーザーとして招待することを選択することができます。
createMatch()新しいターンベースマッチオブジェクトを作成する、または、自動マッチングが要求された場合のユーザーの基準を満たしている既存の試合をロードします。オートマッチングが要求された場合、返される試合は新しい試合または他のプレイヤーがすでにターンを取っている既存の試合のいずれかになります。新しい試合が返された場合、ユーザーは最初のターンを取る必要があります。ゲームは、新規または既存の試合がロードされているかどうかにかかわらず、交替を処理する責任があります。

デフォルトユーザーインターフェースによるプレイヤー選択

Play Games servicesは
public void onStartMatchClicked(View view) {
    Intent intent = 
        Games.TurnBasedMultiplayer.getSelectOpponentsIntent(getApiClient(), 1, 7, true);
    startActivityForResult(intent, RC_SELECT_PLAYERS);
}
以降、未翻訳です。
続きはGoogle Play Game Services — Google Developersを参照してください。


このページのコンテンツはクリエイティブ・コモンズの表示 3.0 ライセンスにより使用許諾されます。サンプル コードは Apache 2.0 ライセンス(リンク先は英語)により使用許諾されます。

2014/05/12

Google Play Services4.3からAPIの一部が変更になっているので、それの対応[リアルタイムマルチプレイヤー編]

Google Play Servicesが3月に4.3(2014/05/12現在は4.4)になり、API周りに変更があります。
 しかしながら、サンプルの方は以前のままでした。今月に入りようやく変更があったので、ButtonClickerを例に記述します。 (※ただし、現時点ではgradle版しか変更されておらず、eclipse版はそのままでした。)

ターンベースマルチプレイヤーについては、ターンベースマルチプレイヤー編の記事を参考にしてください。


final ArrayList invitees = data.getStringArrayListExtra(GamesClient.EXTRA_PLAYERS);
↓
final ArrayList invitees = data.getStringArrayListExtra(Games.EXTRA_PLAYER_IDS);

int minAutoMatchPlayers = data.getIntExtra(GamesClient.EXTRA_MIN_AUTOMATCH_PLAYERS, 0);
↓
int minAutoMatchPlayers = data.getIntExtra(Multiplayer.EXTRA_MIN_AUTOMATCH_PLAYERS, 0);

int maxAutoMatchPlayers = data.getIntExtra(GamesClient.EXTRA_MAX_AUTOMATCH_PLAYERS, 0);
↓
int maxAutoMatchPlayers = data.getIntExtra(Multiplayer.EXTRA_MAX_AUTOMATCH_PLAYERS, 0);

Invitation inv = data.getExtras().getParcelable(GamesClient.EXTRA_INVITATION);
↓
Invitation inv = data.getExtras().getParcelable(Multiplayer.EXTRA_INVITATION);
GamesClient.STATUS_OK
↓
GamesStatusCodes.STATUS_OK
ステータスコードは他にもありますが、GamesClientに定義していたものをGamesStatusCodesにまとめたようです。


参考
playgameservices/android-samples

2014/05/09

Google Play Services4.3からAPIの一部が変更になっているので、それの対応[ターンベースマルチプレイヤー編]

Google Play Servicesが3月に4.3(2014/05/09現在は4.4)になり、API周りに変更があります。
 しかしながら、サンプルの方は以前のままでした。今月に入りようやく変更があったので、SkeletonTbmpを例に記述します。 (※ただし、現時点ではgradle版しか変更されておらず、eclipse版はそのままでした。)

TurnBasedMatch match = data.getParcelableExtra(Games.EXTRA_TURN_BASED_MATCH);
↓
TurnBasedMatch match = data.getParcelableExtra(Multiplayer.EXTRA_TURN_BASED_MATCH);

final ArrayList invitees = data.getStringArrayListExtra(GamesClient.EXTRA_PLAYERS);
↓
final ArrayList invitees = data.getStringArrayListExtra(Games.EXTRA_PLAYER_IDS);

int minAutoMatchPlayers = data.getIntExtra(GamesClient.EXTRA_MIN_AUTOMATCH_PLAYERS, 0);
↓
int minAutoMatchPlayers = data.getIntExtra(Multiplayer.EXTRA_MIN_AUTOMATCH_PLAYERS, 0);

int maxAutoMatchPlayers = data.getIntExtra(GamesClient.EXTRA_MAX_AUTOMATCH_PLAYERS, 0);
↓
int maxAutoMatchPlayers = data.getIntExtra(Multiplayer.EXTRA_MAX_AUTOMATCH_PLAYERS, 0);

GamesClient.STATUS_OK
↓
GamesStatusCodes.STATUS_OK
ステータスコードは他にもありますが、GamesClientに定義していたものをGamesStatusCodesにまとめたようです。


参考
playgameservices/android-samples

2014/04/15

AndroidからAzure Libraries For Java を利用して、AzureのBlob Storageに写真をそのまま追加することはできそうにない

AndroidからAzure Libraries For Java を利用して、AzureのBlob Storageに写真を追加しようと試みましたが、java.lang.VerifyErrorが発生してうまくいきませんでした。


同様の問題を抱えた人が
エラー内容は、 
java.lang.VerifyError: com/microsoft/windowsazure/services/core/storage/utils/Utility

原因は、下記をインポートしているからだと思います。Androidでは使えませんでした。
 import javax.xml.stream.*;

参考

Asp.Netを利用するとうまくいくようです。

(Solved)Using asp.net WebService & Android to upload Image to Azure Blob Storage? - Stack Overflow

2014/04/14

BasaGameUtilsが新しくなり、それに伴い既存プログラムを修正する

BasaGameUtilsが新しくなっていました。 それに伴い、メソッドなどの呼び出しに変更がありましたので、TypeANumberを例に記述します。

startActivityForResult(getGamesClient().getAchievementsIntent(), RC_UNUSED);
↓
startActivityForResult(Games.Achievements.getAchievementsIntent(getApiClient()), RC_UNUSED);

startActivityForResult(getGamesClient().getAllLeaderboardsIntent(), RC_UNUSED);
↓
startActivityForResult(Games.Leaderboards.getAllLeaderboardsIntent(getApiClient()), RC_UNUSED);

getGamesClient().unlockAchievement(getString(R.string.achievement_prime));
↓
Games.Achievements.unlock(getApiClient(), getString(R.string.achievement_prime));

getGamesClient().incrementAchievement(getString(R.string.achievement_really_bored), mOutbox.mBoredSteps);
↓
Games.Achievements.increment(getApiClient(), getString(R.string.achievement_really_bored), mOutbox.mBoredSteps);

getGamesClient().submitScore(getString(R.string.leaderboard_easy), mOutbox.mEasyModeScore);
↓
Games.Leaderboards.submitScore(getApiClient(), getString(R.string.leaderboard_easy), mOutbox.mEasyModeScore);

Player p = getGamesClient().getCurrentPlayer();
↓
Player p = Games.Players.getCurrentPlayer(getApiClient());

2014/01/15

Sound Forge Audio Studio 10.0 に音楽ファイル(mp3)を読み込むと強制終了する

Sound Forge Audio Studio 10.0 にファイル名にスペースを含む音楽ファイル(mp3)を読み込む(ドラッグ&ドロップする)と強制終了しました。

バージョンは、10.0.178および10.0.252(2014/01/15最新)でも強制終了します。

mp3plug2.dllによるものだったので、おそらくコーデックの問題だろうと思い、ソフトを使って変換を行いました(このときは再度mp3に)。

すると強制終了しなくなったので、ひとまず解決しました。

2013/11/28

In-app billing v3のTrivialDriveをAndroid 2.1で動かすとエラーが発生する

Androidアプリでアプリ内課金(in-app billing v3) を実装するために、TrivialDriveを参考にしていると思います。

TrivialDriveでは、Android 2.2(android:minSdkVersion="8")のため問題なかったのですが、もし、Android 2.1(android:minSdkVersion="7")までを対象にしているアプリを作成していた場合、バックボタンやホームボタンでActivityを終了すると、下記のExceptionが発生します。

11-28 19:53:49.412: E/AndroidRuntime(3697): Uncaught handler: thread main exiting due to uncaught exception
11-28 19:53:49.422: E/AndroidRuntime(3697): java.lang.RuntimeException: Unable to destroy activity {jp.example.android.t
rivialdrivesample/jp.example.android.trivialdrivesample.MainActivity}: java.lang.IllegalArgumentException: Service not r
egistered: jp.example.android.trivialdrivesample.util.IabHelper$1@457a5280
11-28 19:53:49.422: E/AndroidRuntime(3697):     at android.app.ActivityThread.performDestroyActivity(ActivityThread.java
:3476)
11-28 19:53:49.422: E/AndroidRuntime(3697):     at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:
3494)
11-28 19:53:49.422: E/AndroidRuntime(3697):     at android.app.ActivityThread.access$2800(ActivityThread.java:123)
11-28 19:53:49.422: E/AndroidRuntime(3697):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1903)
11-28 19:53:49.422: E/AndroidRuntime(3697):     at android.os.Handler.dispatchMessage(Handler.java:99)
11-28 19:53:49.422: E/AndroidRuntime(3697):     at android.os.Looper.loop(Looper.java:123)
11-28 19:53:49.422: E/AndroidRuntime(3697):     at android.app.ActivityThread.main(ActivityThread.java:4370)
11-28 19:53:49.422: E/AndroidRuntime(3697):     at java.lang.reflect.Method.invokeNative(Native Method)
11-28 19:53:49.422: E/AndroidRuntime(3697):     at java.lang.reflect.Method.invoke(Method.java:521)
11-28 19:53:49.422: E/AndroidRuntime(3697):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit
.java:850)
11-28 19:53:49.422: E/AndroidRuntime(3697):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:608)
11-28 19:53:49.422: E/AndroidRuntime(3697):     at dalvik.system.NativeStart.main(Native Method)
11-28 19:53:49.422: E/AndroidRuntime(3697): Caused by: java.lang.IllegalArgumentException: Service not registered: jp.ex
ample.android.trivialdrivesample.util.IabHelper$1@457a5280
11-28 19:53:49.422: E/AndroidRuntime(3697):     at android.app.ActivityThread$PackageInfo.forgetServiceDispatcher(Activi
tyThread.java:934)
11-28 19:53:49.422: E/AndroidRuntime(3697):     at android.app.ApplicationContext.unbindService(ApplicationContext.java:
819)
11-28 19:53:49.422: E/AndroidRuntime(3697):     at android.content.ContextWrapper.unbindService(ContextWrapper.java:342)

11-28 19:53:49.422: E/AndroidRuntime(3697):     at jp.example.android.trivialdrivesample.util.IabHelper.dispose(IabHelpe
r.java:284)

11-28 19:53:49.422: E/AndroidRuntime(3697):     at jp.example.android.trivialdrivesample.MainActivity.onDestroy(MainActi
vity.java:432)
11-28 19:53:49.422: E/AndroidRuntime(3697):     at android.app.ActivityThread.performDestroyActivity(ActivityThread.java
:3463)
11-28 19:53:49.422: E/AndroidRuntime(3697):     ... 11 more


エラーが発生したソースコードの部分は、

IabHelper.java
public void dispose() {
    logDebug("Disposing.");
    mSetupDone = false;
    if (mServiceConn != null) {
        logDebug("Unbinding from service.");
        if (mContext != null) mContext.unbindService(mServiceConn);
        mServiceConn = null;
        mService = null;
        mPurchaseListener = null;
    }
}

です。Android 2.1 は、in-app-billing v3に対応しておらず、Serviceが立ち上がっていなかったのでunbindしようとしたときにエラーが発生しました。
そこで、下記のように修正します。

IabHelper.java
 public void startSetup(final OnIabSetupFinishedListener listener) {
    // If already set up, can't do it again.
    if (mSetupDone) throw new IllegalStateException("IAB helper is already set up.");

    // Connection to IAB service
    logDebug("Starting in-app billing setup.");
    mServiceConn = new ServiceConnection() {
        // 省略
    };

    Intent serviceIntent = new Intent("com.android.vending.billing.InAppBillingService.BIND");
    if (!mContext.getPackageManager().queryIntentServices(serviceIntent, 0).isEmpty()) {
        // service available to handle that Intent
        mContext.bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE);
    }
    else {
        // no service available to handle that Intent
        if (listener != null) {
            listener.onIabSetupFinished(
                    new IabResult(BILLING_RESPONSE_RESULT_BILLING_UNAVAILABLE,
                    "Billing service unavailable on device."));
        }

        mServiceConn = null;// 追加
    }
}

一行追加することで、unbindService(mServiceConn)する直前のmServiceConnの null チェックにより、unbindServiceが呼ばれなくなるのでエラーが発生しなくなります。


ちなみに、最近サンプルコードがrev.5 になっていろいろと修正が加わっていますので、もし以前のサンプルコードを利用している場合は差分を確認することをおすすめします。

2013/11/22

「android.view.WindowManager$BadTokenException: Unable to add window -- 」エラーの対処

Androidアプリを制作中、Thread()を利用してshowDialog(int id)でダイアログを表示した場合、Activityが既に変わっていると下記のエラーが表示されました。

android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy@42d617b8 is not valid; is your activity running?
    at android.view.ViewRootImpl.setView(ViewRootImpl.java:589)
    at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:326)
    at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:224)
    at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java:149)
    at android.view.Window$LocalWindowManager.addView(Window.java:547)
    at android.app.Dialog.show(Dialog.java:285)
    at android.app.Activity.showDialog(Activity.java:3052)
    at android.app.Activity.showDialog(Activity.java:3002)
    at jp.sample.SampleActivity.showReviewDialog(SampleActivity.java:98)
    at android.os.Handler.handleCallback(Handler.java:615)
    at android.os.Handler.dispatchMessage(Handler.java:92)
    at android.os.Looper.loop(Looper.java:213)
    at android.app.ActivityThread.main(ActivityThread.java:4786)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:556)
    at dalvik.system.NativeStart.main(Native Method)


そこで、対象のActivityが終了しているかどうかチェックを行うことで対応できます。

if ( isFinishing() == false ) {
            showDialog( DIALOG_ID );
}


ちなみに、showDialog() は、@Deprecated になっているので注意が必要です。


■参考サイト
progressdialog - Android: "BadTokenException: Unable to add window; is your activity running?" at showing dialog in PreferenceActivity - Stack Overflow

Android: android.view.WindowManager$BadTokenException & Android – Displaying Dialogs From Background Threads


2013/11/21

「ドライバー \Driver\WUDFRd を読み込めませんでした。」が発生したら・・・

ブルースクリーンが発生した際のエラーIRQL_NOT_LESS_OR_EQUALを解決するために、イベントビューアーの管理イベントから、エラーが起きたタイミングで発生していた

警告     2013/11/21 16:39:11     Kernel-PnP     219     (212)

デバイス USB\VID_147E&PID_2016\6&3af1eaa2&0&3 のドライバー \Driver\WUDFRd を読み込めませんでした。
をひとまず解決することにしました。(注:まだ未解決の記事です。)




日記という名の不定記 のサイトを参考に
  1. スタートメニューの「ファイル名を指定して実行」でservices.mscを入力する。
  2. 一覧から、Windows Driver Foundation - User-mode Driver Frameworkを探してWクリックする。
  3. スタートアップの種類を「手動」から「自動」に変更する。

を行いました。

はてさて、これで解決するのかしばらく様子見です。

■2013/11/22追記
変わらずブルースクリーンが発生し(このときはMEMORY_MANAGEMENT)、

警告    2013/11/22 12:52:28    Kernel-PnP    219    (212)
デバイス USB\VID_147E&PID_2016\6&3af1eaa2&0&3 のドライバー \Driver\WUDFRd を読み込めませんでした。


が発生しました。

2013/10/10

Unable to invoke library 'KinectBackgroundRemoval180_64.dll'. の対処法

Kinect SDK 1.8ではBackgroundRemovalBasics-WPFというサンプルが追加されました。
このサンプルでは、カメラ画像から人物を抽出し背景を削除することができます。

このサンプルをそのままカスタマイズしていけば問題は起きなかったのですが、 参考にしながら作成していると、BackgroundRemovedColorStreamのインスタンスを作成するときに、

Unable to invoke library 'KinectBackgroundRemoval180_64.dll'.

が発生しました。

原因は、参照にKinectBackgroundRemoval.dllを追加するだけでは足りず、DLL自体をプロジェクトに追加する必要がありました。

  1. 'KinectBackgroundRemoval180_32.dll'と'KinectBackgroundRemoval180_64.dll'をプロジェクトに追加する
  2. 1で追加したDLLのプロパティを開き、「出力ディレクトリにコピー」の項目に「新しい場合はコピーする(または、常にコピーする)」を選択する
以上で、エラーは解消されました。

'KinectBackgroundRemoval.dll'は、
C:\Program Files\Microsoft SDKs\Kinect\Developer Toolkit v1.8.0\Redist\Microsoft.Kinect.Toolkit.BackgroundRemoval.dll

'KinectBackgroundRemoval180_64.dll'は、
C:\Program Files\Microsoft SDKs\Kinect\Developer Toolkit v1.8.0\Redist\amd64

'KinectBackgroundRemoval180_32.dll'は、
C:\Program Files\Microsoft SDKs\Kinect\Developer Toolkit v1.8.0\Redist\x86

にあります。


余談ですが、Kinectを用いてC#で開発していたときに、Kinectを制御する部分ではないWPF周りで手こずっていました。
Xamlでデータバインディングの仕方やDependencyPropertyがいまいち要領をつかめず。。
Android開発のようにレイアウトはXMLで書いているので似ているのですが。。

そこでXamlについて書かれた本を探したのですが、Xamlでデータバインディングの仕方やDependencyPropertyなどを理解するのに下記の本が非常に分かりやすかったです。
Windowsストアアプリにも興味があったので、ちょうど良いかと思って購入しました。


2013/09/08

Movie Studio Platinum 12が10から良くなったところ

Movie Studio Platinum 12が10から良くなったところのメモを掘り起こしたので公開(2012年11月のものですが、あまり検索しても情報がなかったので) 。

・動画ファイルが増えても快適に編集できる

1番良くなったポイントは、Movie Studio Platinum 12から64bitにも正式(?)に対応したようで、FullHD動画を多く追加しても正常に編集でき、エンコードできるようになったこと。
Vegas Movie Studio HD Platinum 10ではあるライン(*)を超えると編集もままならず(私の環境ではプレビュー画面が赤背景になる)強制終了し、エンコードもできない状態だったので、編集作業が大変楽になった。

(*)あるラインはメモリに関係していると見られ、動画を少なくすると編集が可能でした。仕方がないので、プロジェクトを3つに分け、それぞれエンコードして結合するという手間と時間がかかったことがあります。


・編集時の動作が軽い

Movie Studio Platinum 12の場合、
別のアプリケーションにフォーカスが移ったり、戻ったりしても動作が軽い。
(実行メモリに変動がない)

Vegas Movie Studio HD Platinum 10の場合、
別のアプリケーションからフォーカスが戻ったときに再読み込みするため、扱っている動画が多いほど編集できるまでに時間がかかる。
(待機メモリや実行メモリに変動が大きい)


以上が使ってみて気付いたことです。 
12でメモリの問題が解決されたことが非常に助かったので、アップデートして良かったです。


2013/05/20

【翻訳】Google Play Game Services の設定をGoogle Play デベロッパーコンソール上で行う

Google I/O 2013にて発表されたGoogle Play Game Services について書かれている下記のサイトを翻訳してみました。

Setting Up Google Play Game Services with the Google Play Developer Console
https://developers.google.com/games/services/console/enabling



この資料は、あなたのAndroid, iOS, またはウェブ上のゲームに向けて、デベロッパーコンソールで ゲームサービスを設定する方法を取り扱っています。


ゲームサービスを設定するには、まずデベロッパーコンソールにあなたのゲームを追加する必要があります。ゲームを登録する際、ゲームの名前や説明などの詳細を指定できます。

また、あなたのゲームがゲームサービスにアクセスするためには、ゲームを認証および許可するために必要な証明書を生成する必要があります。

デベロッパーコンソールに登録したゲームは、Android, iOS, またはウェブ版のゲームを関連付けることができるため、プレイヤー達はこれらのプラットフォームで同じゲームの詳細を見たり、同じゲームサービスを共有することができます。


ステップ1.デベロッパーコンソールにサインインする


再インするためには、Google Playデベロッパーコンソールに行きます。もし、これまでにデベロッパーコンソールを登録していなければ、そうするように(=登録するように)求めるメッセージが表示されます。


ステップ2.デベロッパーコンソールにゲームを追加する


デベロッパーコンソールにゲームを追加するためには:
  1. Google Playゲームサービスページを開き、ゲームを追加します。
    • 左側にあるゲームサービスタブを選択します。
    • Google Play ゲームをセットアップボタンをクリックします。
  2. Google APIを既に使用しているゲームを追加しようとしているかどうかを指定します。
    • ゲームをScratchから作ろうとしている場合、または、以前にGoogle APIを設定したことがない場合、ゲームで Google API をまだ使用していませんタブのままでいいです。あなたのゲームの名前を入力し、カテゴリを選択し、そのあと、次へボタンをクリックします。
    • このゲームが既に一つ以上のGoogle API(例えば、Google+ sign-in)を設定している場合は、ゲームで Google API を既に使用していますタブを選択してください。あなたが開発者としてリストされているGoogle APIコンソールからプロジェクトリストを見れます。このリストからプロジェクトを選択し、ゲームのカテゴリを選択し、そのあと、次へボタンをクリックします。

  3. ゲームの詳細フォーム内で、ゲームの説明、カテゴリ、画像アセットを追加します。テスト目的のためでも表示名だけは必須です。その他の項目は、ゲームを公開するときには記入する必要があります。

    • ゲームの表示名と説明は、同じゲームサービスを共有する全てのバージョンに適用するのに十分な、汎用的なものであるべきです。
    • 画像アセットを作成するガイドラインとして、Google Play for Developers guide 及び Google Play Featured-Image Guidelines を参照してください.

  4. デベロッパーコンソール内にゲームのための新しいエントリーを作成するには、保存ボタンをクリックします。

ステップ3.OAuth 2.0クライアントIDを生成する

ゲームにGoogle PlayゲームサービスSDKを使用できるようにするには、まず初めに、あなたのゲームを認証および許可するOAuth 2.0クライアントIDを設定する必要があります。

過去にGoogle APIを使用している場合、既にGoogle APIコンソールでのOAuth 2.0クライアントIDを作成するために使用されるかもしれません。新しいデベロッパーコンソールでは、Google APIコンソールを開くことなく、OAuth 2.0クライアントIDを生成することができます。これを行うには、デベロッパーコンソール内のゲームをGoogle APIコンソールで自動的に生成された対応するエントリーとリンクする必要があります。
OAuth 2.0クライアントIDの生成する方法の詳細については、Google APIs Console helpを参照してください。

警告:あなたのクライアントIDを直接手作業で追加してGoogle APIコンソールを開かないでください。ゲームサービスにリクエストを送信するときにエラーを引き起こす可能性があります。

ゲームのためにOAuth 2.0クライアントIDを生成するには、以下の手順に従います:

a. リンク済みアプリケーションを作成する

Google APIコンソールプロジェクトにゲームをリンクするには、リンク済みアプリページを開き、そしてプラットフォームごとの手順に従います。

以下の手順はAndroidのみの翻訳です。

  1. Android アプリのリンクボタンをクリックします。
  2. アプリ名はプレイヤーに表示されることがあります。そのため、実際のAndroidゲームの名前と一致する名前を指定します。
  3. アプリのパッケージ名を追加します。
  4. ゲームサービスのリアルタイムマルチプレイヤーサポートを使用するには、マルチプレイヤー設定を許可します。
  5. 著作権侵害対策をオンにするかどうかを選択します。
  6. 保存して次へをクリックし、それから下のクライアントIDの作成するセクションの手順に従います。
ここまで。

b. クライアントIDの作成する

  1. ステップ2:アプリの承認画面で、今すぐアプリの承認ボタンをクリックすると、OAuth 2.0クライアントIDを生成する処理が始まります。
  1. オプションとして製品ロゴのほかプロジェクト名を入力するプロンプトが表示されます。この情報は、ユーザーがあなたのゲームを許可するよう求められたとき、OAuth 2.0パーミッションダイアログボックスに表示されます。デフォルトでは、ゲームの名前はプロジェクト名のフィールドに置かれます。
  2. Continueをクリックし、それから下のクライアントID設定を指定するセクションの手順に従います。

c. クライアントID設定を指定する

次に、プラットフォームごとの手順に従って、クライアントID設定を指定します。

以下の手順はAndroidのみの翻訳です。

  1. Application typeとしてInstalled applicationを選び、Installed application typeとしてAndroidを選択します(これらは唯一の選択肢でなければなりません)。
  2. Package nameフィールドには、アンドロイドアプリのパッケージ名を入力します。
  3. ターミナルを開き、SHA-1 フィンガープリント証明書を取得するためにKeytool utilityを実行します。
  4. keytool -exportcert -alias androiddebugkey -keystore <path-to-debug-or-production-keystore> -list -v
    注意:Eclipse用のデバッグキーストアは通常 ~/.android/debug.keystore にあります。

  5. keytoolはキーストアのためのパスワード入力するプロンプトを表示します。デバッグキーストアのデフォルトパスワードは android です。keytoolはターミナルにフィンガープリントを出力します。
  6. 例:
    Certificate fingerprint: SHA1: DA:39:A3:EE:5E:6B:4B:0D:32:55:BF:EF:95:60:18:90:AF:D8:07:09
  7. SHA-1フィンガープリントをSigning certificate fingerprintフィールド内に貼り付けます。
  8. Create clientボタンをクリックし、それから下の資格情報を収集するセクションの手順に従います。
Android上のOAuth 2.0についてさらなる情報については、Authenticating to OAuth2 Services
を参照してください。

注意:あなたのアプリを公開する準備ができたら、デベロッパーコンソール内で新しいクライアントIDを作成する必要があります。次に、リリースに証明書に署名すると、再度次の手順を実行しなければなりません。証明書の署名については、Signing your Applicationを参照してください。

警告:パッケージ名およびこの手順で設定した署名証明書を記録していることを確認してください。アプリケーション内の別の証明書またはパッケージ名を使用すると、認証失敗の原因となります。

注意:デベロッパーコンソール内に同じゲームエントリに複数のAndroidアプリを追加することができます。とはいえ、同じゲームの別のバージョン(例えば、無料版と有料版)がある場合に行われるべきです。このケースでは、常に有料版を無料版(またはデモ/体験版の前にフルバージョン)の前にリストアップします。これは将来のリリースで不正な動作を引き起こす可能性があるので、別のゲームを同じプロジェクトにリンクしないでください。代わりに、デベロッパーコンソールで公開するゲーム毎にゲームエントリを分けて作成します。


ここまで。

d. 認証と承認のための資格情報を収集する

あなたが開発しているプラットフォームに応じて、次の資格情報を見つけて記録する必要があるかもしれません。

クライアントID

Create Clientボタンをクリックすると、このアプリのために新しいクライアントIDが表示されるはずです。後でこの情報が必要になるので、クライアントIDをメモしておいてください。あなたはプラットフォームごとに異なるクライアントIDを持つことになります。



注意:Androidでは、アプリケーションIDから自動的に取得されるように、アプリケーション内の全てのクライアントIDを含める必要はありません。

リンク済みアプリページを再訪問し、あなたのプラットフォームのクライアントIDと関連付けられているリンク済みアプリをクリックすることで、いつでもこの情報を見つけることができます。


クライアントIDはページの下部に記載されています。


Client secret(Webベースのゲームのみ)

webベースのアプリケーションを構築する場合、サーバーベースのAPIクライアントを認証するために、Client secretもまた必要とするかもしれません。Webアプリケーションのリンク済みアプリのエントリーをクリックして、client secretを見つけることができます。

アプリケーションID

また、適切にサインインをセットアップするにはアプリケーションIDを知っておく必要があるかもしれません。それは、ページの上部にゲームの表示名の隣に12または13桁の番号を探すことで、見つけることができます。


e. (オプション)マルチクライアントIDを生成する

マルチプラットフォームで動作するゲームを作っている場合、それぞれのプラットフォーム毎(Web, Android, iOS)のクライアントIDを分けて生成する必要があります。これらを行うには、リンク済みアプリページの別のアプリをリンクボタンをクリックし、リンク済みアプリケーションを作成するセクションから始まる手順を繰り返します。

次の手順

さらに進む前に、テスト用アカウントを有効にするで説明しているように、あなたのゲームにテストアカウントを追加するべきでしょう。許可されたテストアカウントを持つユーザーは、Google Playに未公開のゲームにアクセスし、設定したゲームサービスが正しく機能していることをテストすることができます。

一度上記の初期設定タスクを完了したら、リーダーボードや実績など、あなたのゲームにゲームサービスを構成する手順に進むことができます。、詳しくは、Configuring Google Play Game Serviesを参照してください。

2013/04/30

ThinkPad X201sのHDDを インテル335 Series SSD 240GB に換装しました

ThinkPad X201sのHDDをインテル335 Series SSD 240GB(SSDSC2CT240A4K5)を換装しました。
 OSはWindows 7 Professional SP1(64bit)です。

2年半以上使用してきて、OSの起動にだいぶ時間がかかるようになり、またHDDの応答も悪いことがたまに起こります。そして、SSDの価格に手ごろ感があることから、ついにSSDに交換することにしましたので、交換に至るまでに行った作業をまとめました。


1.不要なファイルを削除する
HDDの中身をSSDにクローンコピーする前にHDDの余分なファイルを削除し、ほとんど使う機会がないデータファイルなどは外付けHDDなどにコピーし、削除しておきます。


2.デフラグを行う
SSDでは基本的に不要のようですが、とりあえず移行前のHDDにデフラグを行っておきました。


3.チェックディスクを行う
チェックディスクをやっておくとコピー時の思わぬトラブルを回避できるのでやっておくのが吉です。
  • チェックディスクは、対象のドライブのプロパティを開き、ツールタブ->エラーチェックの「チェックする」ボタンを押します。
  • 不良セクターをスキャンし、回復するにチェックを入れ、「開始」ボタンを押せば実行できます。
  • Cドライブの場合は再起動が必要です。

チェックディスクを行わずにクローンコピーを行ったら、途中で読み込みできないセクターがあると出て「再試行、無視、すべて無視(?)、キャンセル」のコマンドを選べました。「すべて無視」を選択してコピー作業を継続できましたが、念のためチェックディスクを行って再度クローンコピーを行うことにしました。


4.クローンコピー
クローンコピーには、IntelR Data Migration Softwareを利用しました。HDD 250GB ->SSD 240GBと容量は小さくなりますが、元の使用している容量を240GBより小さくしておけば特に問題なくできました。

HDDの交換方法(ラップトップ本体への取り付け)はこちらのサイトを参考にしました(写真があって分かりやすいです)。
カイカイカウカウ: ThinkPad X201のHDDをSSDに換装した。

一つ付け加えると、HDDを取り出すときにHDDトレイの黒いベロの部分を取り出すのに手こずったので、細いドライバーを間に挟んで取り出しました。


■結果
ベンチマークソフトのビフォー/アフターの結果は以下のようになりました。




・左  :HDD(250GB ハード・ディスク・ドライブ, 7200rpm/FDE対応)
・中央:SSD(インテル335 Series SSD 240GB)
・右  :SSD(Intel SSD Toolboxオプティマイズ後)
HDD(左)と比べSSD(中央)は格段に早くなっています。読み込み/書き込みともに2.4倍以上になっており、実際にこれまで起動に3分かかっていたものが、1分~1分30秒で起動するようになり快適になりました。大変満足です。

そして、Intel SSD Toolboxを使ってオプティマイズしてみた結果は右のようになりました。
あまり変わらない、というかむしろ全体的に下がってる印象なので通常のスコアが特に低くなければ使わなくても良いかも(誤差の範囲内と思うことにしています)。


ちなみに、これまでのHDDはウルトラベースのハードディスクドライブ・ベイアダプターに載せて使い、しばらくしたらフォーマットをかける予定です。
レノボ・ジャパン ThinkPadシリアルATA HD・ベイ・アダプターII 43R1980はSATA HDD・ベイアダプターIII 43N3412の画像になって少し不安になりますが、購入した結果はベイアダプターでした)


2012/11/21

DVD Architect Studio 5.0 をアップデートしたらソフトを起動できなくなった

Vegas Movie Studio HD Platinum 10 Production Suite(パッケージ版)から Movie Studio Platinum 12 Suite(ダウンロード版)にアップデートした際、Sound Forge Audio Studio 10.0 や DVD Architect Studio 5.0 もついでにアップデートを行いました。

Sound Forge Audio StudioやDVD Architect Studioは、Buildバージョンが少し上がってる程度です。

■Sound Forge Audio Studioのアップデート
"audiostudio10.0.178.exe"をダウンロードし、実行するとアップデートが行われます。
 新しいシリアル番号を入力することなく使えました。

■DVD Architect Studioのアップデート
  1. "dvdarchitectstudio5.0.161.exe"をダウンロードし、実行するとアップデートが行われます。しかし、実行ファイルが消えて、DVD Architect Studioソフトウェアを起動できなくなりました
  2. 仕方がないので、コントロールパネルからアンインストールを行い、再びインストーラを起動してインストールを行うことで正常にアップデート(実際にはインストール)できました。
  3. 再インストールの形になったので、新しいシリアル番号を入力して使えるようになりました。

Sound Forge Audio StudioやDVD Architect Studioの2つのソフトウェアをアップデートする利点はバグ修正ぐらいだと思いますが、Vegas Movie Studio HD Platinum 10 Production SuiteからMovie Studio Platinum 12 Suiteへのアップデートを行う利点は64bit対応など大きいものがありますのでそちらはオススメです。


2012/11/06

[Google App Engine Java] Bad version number in .class file エラーを解決する

Google Plugin for Eclipse を利用してプロジェクトを作成した際、java.lang.UnsupportedClassVersionError: Bad version number in .class file
が発生したので、その修正方法をさっくりと記します。


■環境
  • Windows 7 Professional 64bit
  • eclipse 3.6.2
  • Google App Engine Java SDK 1.7.3 Bundle for Eclipse
  • Google Plugin for Eclipse 3.6(3.1.1.v201210291355-rel-r36) 

■解決法
  1. 「プロジェクト」を右クリックし、「プロパティ」を選択します。
  2. 「Java コンパイラー」を選択し、「コンパイラー準拠レベル」が1.6であることを確認します。下の方にエラーが出ていたら、その指示に従ってエラーを修正します。
  3. 今回の場合、Java のビルド・パスに jre1.5が設定されていたために起こったエラーだったので、ビルド・パスを「インストール済みのJRE[jre1.6]」に変更しました。

以上の手順でエラーを解消しました。

2012/10/29

Google App Engine では M2Crypto は使えない?

Android のアプリ内課金(In-App Billing)はサーバー認証を行うべきだというのは書かれているのですが、その方法は日本語サイトではあまり見かけません(セキュリティに関することなので、出てこないのかもしれません)。
そこで、Google App Engine(GAE) を使って、サーバー認証しようと思いました。GAEではPythonとJavaとGOが利用できるので、今回はPythonで作ろうと思いました。

PHPで作成するなら以下のサイトが参考になります。
In-app Billingでsignatureの検証をサーバサイドで行う - isherの日記
android in-app Billingのサーバ側チェック - 私事ですが……


さて、本題。

環境:Windows 7 Professional 64bit, Python2.7(64bit), App Engine SDK 1.7.2

Python でのサーバー認証の方法は以下を参考に M2Crypto を使用してみましたが、
Verifying signature on android in-app purchase message in Python on Google App Engine - Stack Overflow


File "C:\dev\gae\appName\M2Crypto\__init__.py", line 22, in
ImportError: No module named __m2crypto


と、M2Crypto のインポートエラーが出ます。調べてみると、

python - importing m2crypto to google app engine - Stack Overflow
  m2crypto contains C code and won't work on GAE(C言語を含むm2cryptoはGAE上では動かない。)
 と書かれていました。

■結論
 __m2crypto.pyd はC言語で書かれた拡張モジュール(=pyd)なので、GAEでは利用できないのだと思います。
(が、参考にしたソースは「この方法でできたよ(Here's how i did it)」って書かれてるので、できるのかな~という気はしますが。。)



■余談
Pythonの基礎については以下のサイトでPDFを無料で公開されていますので、こちらも利用しています。
みんなのPython Webアプリ編 | Lindoc