2016年6月24日金曜日

Android Wearな端末一覧

発売日は適当。国によって発売日が異なっていたりして。(それなりに世代順に並べられればなという程度。)

機種名 LG G Watch Samsung Gear Live Moto 360
(1st Gen)
LG G Watch R ZenWatch
(WI500Q)
SmartWatch 3 LG Watch Urbane Huawei Watch Moto 360
(2nd Gen)
ZenWatch2
(WI501Q/WI502Q)
LG Watch Urbane
2nd Edition
TAG Heuer
Connected
Moto 360 Sport Smart Outdoor Watch
WSD-F10
発売日 2014年6月25日 2014年6月25日 2014年9月5日 2014年11月12日 2014年11月21日 2014年11月28日 2015年4月27日 2015年9月2日 2015年9月14日 2015年11月13日 2015年11月12日 2015年11月12日 2015年12月18日 2016年3月25日
ディスプレイ 1.65-inch
IPS
1.63-inch
Super AMOLED
1.56-inch
IPS
1.3-inch
P-OLED
1.63-inch
Super AMOLED
1.6-inch
TFT
1.3-inch
P-OLED
1.4-inch
AMOLED
1.56-inch/1.37-inch
IPS
1.63-inch/1.45-inch
AMOLED
1.38-inch
P-OLED
1.5-inch
LTPS
1.37-inch
AnyLight Hybrid Display
1.32-inch
カラーTFT+モノクロ
形状 Square Square Round Chin Round Square Square Round Round Round Chin Square Round Round Round Chin Round Chin
解像度 280x280 320x320 320x290 320x320 320x320 320x320 320x320 400x400 360x330/360x325 320x320/280x280 480x480 360x360 360x325 320x300
CPU Snapdragon 400
1.2GHz
Snapdragon 400
1.2GHz
OMAP 3
1.0GHz
Snapdragon 400
1.2GHz
Snapdragon 400
1.2GHz
Snapdragon 400
1.2GHz
Snapdragon 400
1.2GHz
Snapdragon 400
1.2GHz
Snapdragon 400
1.2GHz
Snapdragon 400
1.2GHz
Snapdragon 400
1.2GHz
Atom Z34XX
1.6GHz
Snapdragon 400
1.2GHz
メモリ 512MB 512MB 512MB 512MB 512MB 512MB 512MB 512MB 512MB 512MB 768MB 1GB 512MB 512MB
ストレージ 4GB 4GB 4GB 4GB 4GB 4GB 4GB 4GB 4GB 4GB 4GB 4GB 4GB 4GB
Bluetooth 4.0 4.0 4.0 4.0 4.0 4.0 4.1 4.1 4.0 4.1 4.1 4.1 4.0 4.1
Wi-Fi - -
スピーカー - - - - - - - - - -
GPS - - - - - - - - - -
心拍数センサー - - - -
加速度センサー
ジャイロセンサー
磁気センサー - - - - -
光センサー - - - - - - - - -
気圧センサー - - - - - - -
防水/防塵 IP67 IP67 IP67 IP67 IP55 IP68 IP67 IP67 IP67 IP67 IP67 IP67 IP67 5気圧
その他 - - - - - - - - - - LTE/3G - - MIL-STD-810G

2016年6月22日水曜日

UnityでAmbisonicな録音を試みる

YouTubeさんのSpatial Audio(空間音声)対応を見かけて興味が湧いたところに

360 度動画や VR 動画で空間音声を使用する - YouTube ヘルプ
https://support.google.com/youtube/answer/6395969?hl=ja

こちらのブログ記事と出会ったのでUnityで試してみたメモ。

niu log: 4chサラウンドをAmbisonicsに変換する
http://niulog.blogspot.jp/2016/05/4chambisonics.html

環境

Unity 5.3.5
OS X Yosemite(10.10.5)
Soundflower 2.0b2

準備

4chサラウンドをAmbisonicに変換するということなので
Unityのオーディオ設定でサラウンドを使用するのですが(DefaultはStereo)
こちらの設定はPCのオーディオデバイスがStereo(2ch)出力だと
サラウンド設定が有効にならないようなので(Stereo(2ch)として出力される)
Soundflower(仮想オーディオデバイス)を使用しました。
※Soundflowerの導入方法はここでは割愛しますので、Web検索等で調べてください

Soundflowerがインストールされた状態でMacの[Audio MIDI 設定]を開き
サウンド出力装置をSoundflower(64ch)に変更します。
[出力]の[スピーカーを構成...]を開き



[マルチチャンネル]の[4チャンネル]に設定します。



Unityを起動し、AudioManager([Edit] -> [Project Settings] -> [Audio])の
[Default Speaker Mode]を[Quad]に設定します。



Quadは前左右、後左右の4chです。

Unity - スクリプトリファレンス: AudioSpeakerMode.Quad http://docs.unity3d.com/ja/current/ScriptReference/AudioSpeakerMode.Quad.html

※Unityは起動時にオーディオデバイスをチェックしているようなので
 Soundflowerの設定前に既にUnityを起動していた場合は再起動してください。

コード

wxyzチャネルの並び順は上記YouTubeさんのヘルプに
wyzx云々と書いてあったので(よく意味は分かっていない...)
その並びでWAVEファイルを作っています。

Unityのシーン内のオーディオをWAVEファイルに録音する方法は下記を
Writing AudioListener.GetOutputData to wav - problem | Unity Community
http://forum.unity3d.com/threads/writing-audiolistener-getoutputdata-to-wav-problem.119295/

また、WAVEファイルのヘッダ構造はこちらのサイトを参考にさせていただきました。
WAVEファイルの構造
http://www.graffiti.jp/pc/p030506a.htm

using UnityEngine;
using System;
using System.Collections;
using System.IO;

public class AmbisonicRecorder : MonoBehaviour
{
 private int outputRate = 44100;
 private string fileName = "output.wav";
 private int headerSize = 44;
 //default for uncompressed wav
 private int ambisonicChannels = 4;
 private bool recOutput;
 private FileStream fileStream;

 // Use this for initialization
 void Start ()
 {
  Debug.Log (AudioSettings.driverCapabilities);

  StartWriting (fileName);
  recOutput = true;
 }
 
 // Update is called once per frame
 void Update ()
 {
 }

 void OnDestroy ()
 {
  recOutput = false;
  WriteHeader ();
 }

 void OnAudioFilterRead (float[] data, int channels)
 {
  // Debug.Log("data.Length:" + data.Length + "/channels:" + channels);
  if (recOutput) {
   short[] shortData = new short[data.Length];
   //converting in 2 steps : float[] to short[], //then short[] to Byte[]

   byte[] bytesData = new Byte[data.Length * 2];
   //bytesData array is twice the size of
   //dataSource array because a float converted in short is 2 bytes.

   int rescaleFactor = 32767; //to convert float to short

   //Ambisonic
   int index = 0;
   for (int i = 0; i < data.Length; i += channels) {
    float frontL = data [i];
    float frontR = data [i + 1];
    float backL = data [i + 2];
    float backR = data [i + 3];

    float front = (frontL + frontR) / 2.0f;
    float back = (backL + backR) / 2.0f;
    float left = (frontL + backL) / 2.0f;
    float right = (frontR + backR) / 2.0f;

    float w = (frontL + frontR + backL + backR) / 4.0f;
    float x = front - back;
    float y = left - right;
    float z = 0.0f;

    // Debug.Log ("w:" + w + "/x:" + x + "/y:" + y + "/z:" + z);
    for (int j = 0; j < ambisonicChannels; j++) {
     float writeData = 0.0f;
     switch (j) {
     case 0:
      writeData = w;
      break;
     case 1:
      writeData = y;
      break;
     case 2:
      writeData = z;
      break;
     case 3:
      writeData = x;
      break;
     }
     byte[] bytes = new Byte[2];
     shortData [index] = (short)(writeData * rescaleFactor);
     bytes = BitConverter.GetBytes (shortData [index]);
     bytes.CopyTo (bytesData, index * 2);
     index++;
    }
   }

   if (!recOutput) {
    return;
   }
   fileStream.Write (bytesData, 0, bytesData.Length);
  }
 }

 private void StartWriting (string name)
 {
  fileStream = new FileStream (name, FileMode.Create);
  byte emptyByte = new byte ();

  for (int i = 0; i < headerSize; i++) { //preparing the header
   fileStream.WriteByte (emptyByte);
  }
 }

 private void WriteHeader ()
 {

  fileStream.Seek (0, SeekOrigin.Begin);

  byte[] riff = System.Text.Encoding.UTF8.GetBytes ("RIFF");
  fileStream.Write (riff, 0, 4);

  byte[] chunkSize = BitConverter.GetBytes (fileStream.Length - 8);
  fileStream.Write (chunkSize, 0, 4);

  byte[] wave = System.Text.Encoding.UTF8.GetBytes ("WAVE");
  fileStream.Write (wave, 0, 4);

  byte[] fmt = System.Text.Encoding.UTF8.GetBytes ("fmt ");
  fileStream.Write (fmt, 0, 4);

  byte[] subChunk1 = BitConverter.GetBytes (16);
  fileStream.Write (subChunk1, 0, 4);

  byte[] audioFormat = BitConverter.GetBytes (1); //Uncompressed PCM
  fileStream.Write (audioFormat, 0, 2);

  byte[] numChannels = BitConverter.GetBytes (ambisonicChannels);
  fileStream.Write (numChannels, 0, 2);

  byte[] sampleRate = BitConverter.GetBytes (outputRate);
  fileStream.Write (sampleRate, 0, 4);

  byte[] byteRate = BitConverter.GetBytes (outputRate * 2 * ambisonicChannels);
  // sampleRate * bytesPerSample*number of channels, here 44100 * 2 * 4
  fileStream.Write (byteRate, 0, 4);

  byte[] blockAlign = BitConverter.GetBytes (8);
  // 16bit * number of channels, here 16bit * 4 = 64bit = 8byte
  fileStream.Write (blockAlign, 0, 2);

  byte[] bitsPerSample = BitConverter.GetBytes (16);
  fileStream.Write (bitsPerSample, 0, 2);

  byte[] dataString = System.Text.Encoding.UTF8.GetBytes ("data");
  fileStream.Write (dataString, 0, 4);

  byte[] subChunk2 = BitConverter.GetBytes (fileStream.Length - headerSize);
  fileStream.Write (subChunk2, 0, 4);

  fileStream.Close ();
 }
}

使い方

AmbisonicRecorder.csをAudioListenerコンポーネントがアタッチされているGameObjectにアタッチします。

Unity EditorのPlay Mode開始〜終了まで録音します。

4ch前提で作っていますのでStart()内のDebug.Log()で
”Quad”とConsoleに表示されることを確認します。

作成されたWAVEファイルはプロジェクトディレクトリ直下に
output.wavというファイル名で出力されます。

プレビュー

プレビューにはJump Inspectorを使用しました。



Jump InspectorはGoogleさんがPlay Storeのベータプログラムで公開している
360度動画ビューアーアプリでSpatial Audioにも対応しています。
因みにSpatial Audioなオーディオファイルのみでもプレビュー可能。
対応端末が
・Samsung Galaxy S6
・Nexus 6P
なのが。。(その他の端末で動かないのかは試してません)

Jump Inspector Overview - Jump Help https://support.google.com/jump/answer/6400241?hl=en
※Play Storeのベータプログラムとして公開されているのでベータ登録が必要です。

デモ

作成したVR動画をYouTubeにアップしました。
音源が付いた車が自分の周りをぐるぐる回ります。
※デモが微妙でゴメンナサイ。。
因みに、この記事を書いている時点でYouTubeの空間音声が体験できるのは
バージョン 4.2 以降の Android 端末で YouTube Android アプリを利用している
場合のみとなっています。
ヘッドフォン・イヤフォンを付けて視聴してみてください。
どうですかね、音の聞こえ方。

2015年5月15日金曜日

Oculus Mobile SDK Unity IntegrationのProjectSettingsを差分ツールで眺めてみた


はじめに

 新規プロジェクトの場合はプロジェクト作成時に忘れないようにProjectSettingsを上書きすれば良いですが、既存プロジェクトをGear VRに移植する場合は既存のProjectSettingsにOculus Mobile SDK Unity IntegrationのProjectSettingsの設定を適用したいケースもあるかと思い調べてみました。

環境

Oculus Mobile SDK 0.5.1
Unity 4.6.5p1

調査方法

 Unity 4.6.5p1で新規作成したプロジェクトのProjectSettingsとOculus Mobile SDK Unity IntegrationのProjectSettingsを差分ツールで比較。
※Oculus Mobile SDK Unity IntegrationのProjectSettingsはUnity 4系のものであると思われるため、Unity 5ではなくUnity 4.6.5p1と比較
※新規作成したプロジェクトのProjectSettingsディレクトリ配下のファイルはバイナリ形式であるため[Edit] - [Project Settings] - [Editor]の[Asset Serialization]のModeを[Force Text]に変更してから差分ツールで比較を実施
※Oculus Mobile SDK Unity IntegrationのProjectSettingsはテキスト形式

差分

・InputManager.asset
 [Edit] - [Project Settings] - [Input]
  ここは上書きでも良いかなと思うので割愛

・TagManager.asset
 [Edit] - [Project Settings] - [Tags and Layers]
  Layers
   User Layer 8:IgnoreBlobShadow

・QualitySettings.asset
 [Edit] - [Project Settings] - [Quality]
  ここは上書きでも良いかなと思うので割愛

・EditorSettings.asset
 [Edit] - [Project Settings] - [Editor]
  Version Control
   Mode:Visible Meta Files(Gear VRと特に関係無さそう)
  Sprite Packer
   Mode:Disabled

・NavMeshAreas.asset
 Oculus Mobile SDK側にのみ存在

・ProjectSettings.asset
 [Edit] - [Project Settings] - [Player]
  ここは上書き後に必要な項目を修正した方が効率良さそうなので割愛
  Company Name/Product Name/Icon/Bundle Identifier等

まとめ

Input/Quality/Player設定の上書きが許容できるのであれば、差分はそんなに多くない。

2015年4月2日木曜日

360度動画の底にロゴを表示する

環境

・Mac
・Blender 2.74
・Premiere Pro CC 2014

手順

1. Cycles Renderに切り替え


2. Lensの設定
 カメラを選択して
 [Panoramic]
 Typeを[Equirectangular]
 に設定


3. Circleを作成
 3D View上で[shift]+[A]
 [Mesh]-[Circle]


 円を滑らかにするために[Vertices]を256
 デフォルトでは面が無いので[Fill Type]を[Triangle Fan]にして面を作成



4. UV展開
 作成したCircleを選択した状態で[tab]キーでEdit Modeへ
 [UV Mapping]で[Cube Projection]を選択


5. マテリアル作成
 [New]からマテリアルを作成


 [Color]の右端のボタンをクリック
 [Image Texture]を選択


 ロゴ画像を指定


 画像はみかんにゃさんの「ずん子マーク2」を使わせて頂きました。
 【ずんきょ】みかんにゃさんのイラストを追加しました! | 東北ずん子ポータル
  http://t-zunko.moe/2015-03-11-mikannya

 3D ViewのViewport Shadingを[Material]に変更


 テクスチャが表示されるとこんな感じ


6. カメラの位置・角度調整
 カメラを選択してスクリーンショットの通りに位置・角度を調整
 ※このメニューは3D Viewで[N]キーを押すと表示される


7. ライトの位置・角度調整
 ライトを選択してスクリーンショットの通り位置・角度を調整


8. レンダリング解像度と透過の設定
 解像度を設定
 ロゴ以外の部分は透過でレンダリングして動画に合成したいので
 [Film]の[Transparent]にチェック



9. レンダリングと画像書き出し
 レンダリング実行


[F3]キーで画像を書き出し


10. Premiereで合成
 Blenderで書き出したロゴをPremiereのタイムラインにドラッグ&ドロップ
 動画の尺にロゴ画像を合わせる


仕上がり

アキバ ホコ天(2015.03.22) | ハコスコストア


最後に

 Blender Lv.1なのでツッコミお待ちしております。
 そもそも、Blender使わなくてももっと簡単に出来るよ!とかあれば教えてください。

2015年3月26日木曜日

AndroidなUnityのGamepad for Nexus Player キーアサイン

環境

Unity 5.0.0p2
Nexus 5(Android 5.1)

キーアサイン

joystick button 0(Fire1)
A
joystick button 1(Fire2)
B
joystick button 2(Fire3)
X
joystick button 3(Jump)
Y
joystick button 4
L1
joystick button 5
L2
X axis
Analog Stick Left ←→
Y axis
Analog Stick Left ↑↓
3rd axis
Analog Stick Right ←→
4th axis
Analog Stick Right ↑↓
5th axis
←→
6th axis
↑↓
7th axis
L2
8th axis
R2

因にペアリングをクリアして他の端末とペアリングしたい時は
電源ONの状態で「戻る」ボタンと「ホーム」ボタンを押しながら
「電源」ボタンを長押しのようです。
そうするとLEDx4が点滅に変わってペアリング待ちの状態になりました。

Unity Remote 4経由でゲームパッドの入力取れたらデバッグ楽かな
と思って試してみたけど出来ないようです。

2014年7月25日金曜日

Android StudioでUnityのNative Plugin(jar)をつくる

Gradleについてあまり詳しくないですが、とりあえずHello World的なものが動いたのでメモ。

環境

OS X Mavericks 10.9.4
Android Studio (Beta) 0.8.2
Unity 4.5.2f1

空のプロジェクトを作成

Android Studioで[Add No Activity]を選択して空のプロジェクトを作成。

jarファイルの追加


classes.jarファイルをプロジェクトのlibsフォルダにコピー。
Macの場合のパス
<Unityインストールディレクトリ>/Unity.app/Contents/PlaybackEngines/AndroidPlayer/release/bin/classes.jar

android.jarファイルをプロジェクトのlibsフォルダにコピー。
パス
<Android SDK Root>/platforms/android-19/android.jar
※今回はAndroid 4.4のjarを使用

Sync Project with Gradle Files


Native Plugin側のコード

<Project Root>/app/src/main/java/<Package Name>/配下にJava Classを新規作成。
適当にToastを表示するだけのプラグインを作成。

package com.example.unityplugin;

import android.app.Activity;
import android.widget.Toast;

import com.unity3d.player.UnityPlayer;

public class AndroidNative {
    public static void showToast() {
        final Activity activity = UnityPlayer.currentActivity;
        activity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(activity, "Hello Native Plugin!", Toast.LENGTH_SHORT).show();
            }
        });
    }
}

build.gradleの編集

// apply plugin: 'com.android.application'
apply plugin: 'java'

jar.baseName = 'android-native-plugin'
version = '1.0.0'

//android {
//    compileSdkVersion 20
//    buildToolsVersion "20.0.0"
//
//    defaultConfig {
//        applicationId "com.example.unityplugin"
//        minSdkVersion 15
//        targetSdkVersion 20
//        versionCode 1
//        versionName "1.0"
//    }
//    buildTypes {
//        release {
//            runProguard false
//            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
//        }
//    }
//}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
}

jarファイルの作成

Android StudioのTerminalを開き下記のコマンドを実行。
./../gradlew jar


jarファイルは下記のディレクトリ配下に作成される。
<Project Root>/app/build/libs/

作成したjarファイルをUnityプロジェクトのAssets/Plugins/Android/ディレクトリ配下に配置。

呼び出し側コード

using UnityEngine;
using System.Collections;

public class Toast : MonoBehaviour {

 // Use this for initialization
 void Start () {
  AndroidJavaClass androidNativePlugin = new AndroidJavaClass("com.example.unityplugin.AndroidNative");
  androidNativePlugin.CallStatic("showToast");
 }
 
 // Update is called once per frame
 void Update () {
 
 }
}

動作確認


2014年3月28日金曜日

Unreal Engine 4でFPSを表示する方法


[`]キーで画面下部にプロンプトが表示されるので
表示されたプロンプトに「Stat FPS」と入力する。
※プロンプトでのコマンド入力時はTABキーで補完が使える


Editor上でPlay中は右上のEnter console commandと表示されているところに「stat fps」と入力する。


2014年3月12日水曜日

AndroidなUnityのDUALSHOCK4 キーアサイン

環境

Unity 4.3.4
Xperia Z1

キーアサイン

oystick button 0
joystick button 1
×
joystick button 2
joystick button 3
L1
joystick button 4
L2
joystick button 5
R2
joystick button 6
SHARE
joystick button 7
OPTIONS
joystick button 8
Touch Pad Click
joystick button 10
Analog Stick Right Click
joystick button 11
Analog Stick Left Click 
joystick button 12
PS BUTTON
joystick button 13
joystick button 14
R1
X axis
Analog Stick Left ←→
Y axis
Analog Stick Left ↑↓
3rd axis
Analog Stick Right ←→
4th axis
Analog Stick Right ↑↓
5th axis
←→
6th axis
↑↓

AndroidなUnityのDUALSHOCK3 キーアサイン

環境

Unity 4.3.4
Xperia Z1

キーアサイン

joystick button 0
joystick button 1
joystick button 2
×
joystick button 3
joystick button 4
L1
joystick button 5
R1
joystick button 6
L2
joystick button 7
R2
joystick button 8
Analog Stick Left Click
joystick button 9
Analog Stick Right Click
joystick button 10
START
joystick button 11
SELECT
joystick button 15
PS BUTTON
X axis
Analog Stick Left ←→
Y axis
Analog Stick Left ↑↓
3rd axis
Analog Stick Right ←→
4th axis
Analog Stick Right ↑↓
5th axis
←→
6th axis
↑↓

2014年3月11日火曜日

アプリからIntent連携でツイートする

こちらの投稿を見て試してみたのでメモしておく。
投稿者の方に感謝。

Android - Twitterに共有するIntentの書き方 - Qiita
http://qiita.com/gari_jp/items/7e30eba5de3b470a59cf

コード

String url = "http://twitter.com/share" +
        "?text=てすと" +
        "&url=http://www.google.com" +
        "&via=kojiokb" +
        "&hashtags=hoge";
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));

動作確認

上記のコードのIntentの内容ですと、こんな感じに。

以下のTwitterクライアントでツイートできることを確認。
・Twitter公式クライアント
・twicca
・TwitPane

WebのツイートボタンのURLに対応したTwitterクライアントなら、この方法でツイートできるということなのかな?

参考

Tweet Button | Twitter Developers
https://dev.twitter.com/docs/tweet-button

MacなUnityのDUALSHOCK4 キーアサイン

USB接続で確認。
Bluetooth接続はペアリングは成功するが動作せず。

環境

Mac OS X Mavericks 10.9.2
Unity 4.3.4

キーアサイン

joystick button 0
joystick button 1
×
joystick button 2
joystick button 3
joystick button 4
L1
joystick button 5
R1
joystick button 6
L2
joystick button 7
R2
joystick button 8
SHARE
joystick button 9
OPTIONS
joystick button 10
Analog Stick Left Click
joystick button 11
Analog Stick Right Click
joystick button 12
PS BUTTON
joystick button 13
Touch Pad Click
X axis
Analog Stick Left ←→
Y axis
Analog Stick Left ↑↓
3rd axis
Analog Stick Right ←→
4th axis
Analog Stick Right ↑↓
5th axis
L2
6th axis
R2
7th axis
←→
8th axis
↑↓

2014年3月2日日曜日

MacなUnityのDUALSHOCK3 キーアサイン

環境

Mac OS X Mavericks 10.9.2
Unity 4.3.4

キーアサイン

joystick button 0
SELECT
joystick button 1
Analog Stick Left Click
joystick button 2
Analog Stick Right Click
joystick button 3
START
joystick button 4
joystick button 5
joystick button 6
joystick button 7
joystick button 8
L2
joystick button 9
R2
joystick button 10
L1
joystick button 11
R1
joystick button 12
joystick button 13
joystick button 14
×
joystick button 15
joystick button 16
PS BUTTON
X Axis
Analog Stick Left ←→
Y Axis
Analog Stick Left ↑↓
3rd Axis
Analog Stick Right ←→
4th Axis
Analog Stick Right ↑↓

2014年1月19日日曜日

Unity(Android)のShow Loading Indicator

UnityでAndroidビルド向けの[Show Loading Indicator]の動作を確認してみたのでメモ。
Inversedは何が変わるのかよくわからず。

Large

Inversed Large

Small

Inversed Small

2013年11月9日土曜日

LogCatの小窓から(Android Studio編)

Android StudioのLogCatは彩りが足りない!
ので、
彩りを加えてみたメモ。

環境

Mac OS X Mavericks
Android Studio 0.3.4

Before


設定方法

[Preferences] -> [Editor] -> [Colors & Fonts] -> [Android Logcat]を開く。

まず、デフォルトのテーマは変更できないので[Save As...]からコピーを作成する。

[Inherit Attributes From:]のチェックを外す。

カラーの四角いとこを右クリックするとカラーピッカーが開くので、各ログレベルの色をカスタマイズしていく。

今回は見慣れたあのIDEの色に変更した。
Verbose #000000
Debug #00007F
Info #007F00
Warning #FF7F00
Error #FF0000
Assert #FF0000

After


見慣れたあの感じになりました。

Androidの外部ストレージ容量不足時のテスト

方針

外部ストレージにダミーファイルを作成して、容量不足の状況を意図的に作り出します。

ダミーファイル作成

ダミーファイルは下記のコマンドで作成します。
adb shellで端末のシェルに入り、ダミーファイルを作成したいディレクトリに移動してからコマンドを実行してください。
dd if=/dev/zero of=dummy.file bs=1048576 count=1000
この例では1GBのダミーファイルを作成しています。
外部ストレージの容量を食い尽くすまで、ファイル名を変えながらコマンドを実行します。
最後の微調整はcountを弄って調整してください。
(bsが1MBなので、10MBならcountを10にします)
動作確認した端末では1GBのダミーファイルを作成するのに2分ほどかかりました。

ダミーファイルの作成をローカルで行ってadb pushで実機に転送する方法もありますが、僕の確認した環境ですと
ダミーファイル作成:1秒
ファイル転送:3分
となり、遅くなってしまったので端末側でダミーファイルを作成する手順にしています。

まとめ

いまどきのストレージ容量の大きな端末では、ダミーファイルで埋めていくのが大変かと思います。
一昔前の端末 + 容量の小さいMicro SDカード(試供品で付いてくるやつとか)
があるとテストが捗るかもしれません。

エミュレータで外部ストレージ容量の小さいイメージを作成してテストするとかも有効かもしれませんが、実機でもっとスマートな方法をご存知でしたら教えてください。

2013年11月6日水曜日

実測でみるAndroidのステータスバー/ナビゲーションバーサイズ

ステータスバー/ナビゲーションバー

・ステータスバー
 ディスプレイ上部のアンテナピクト・バッテリー残量・時刻などを表示するエリア


・ナビゲーションバー
 ディスプレイ下部の戻る・ホーム・タスクボタンを表示するエリア
(ホームボタン等がハードウェアキーの場合は、ナビゲーションバーは表示されない)


測定結果

・Portrait
 ステータスバー:25dp
 ナビゲーションバー:48dp
・Landscape
 ステータスバー:25dp
 ナビゲーションバー:42dp
※Landscape時はナビゲーションバーの高さというか幅が少し狭くなるので注意ですね

現在主流(?)のアスペクト比16:9のスマートフォン端末(FHD/HD/QHD)ですと、画面いっぱいがdp換算で640dp × 360dpなので、ステータスバー/ナビゲーションバーを差し引いた567dp × 360dpがアプリで使える領域となります。(Portraitの場合)

各dpiにおけるpx数は
dp × density
で得られます。

dpi density
ldpi
0.75
mdpi
1
hdpi
1.5
xhdpi
2
xxhdpi
3
xxxhdpi
4

測定方法

EclipseのDDMSパースペクティブにある
「Dump View Hierarchy for UI Automator」を使用。
(この機能が使えるのはAndroid 4.1以上)
こんな感じでViewを選択して表示される座標から測定。
座標の読み方は[left, top][right, bottom]です。


測定に使用した端末

Nexus 5
Xperia Z(SO-02E)
AQUOS PHONE EX(SH-04E)

補足

Android 4.4からはステータスバー/ナビゲーションバーの背景部分もアプリの描画領域として使えるようです。
「Translucent bars」の項を参照。
Ryosuke's Memo
"Android Design in Action: New in Android 4.4" 動画番組の概要 (日本語)
http://ryosuke-memo.blogspot.jp/2013/11/android-design-in-action-new-in-android.html

2013年11月1日金曜日

Git 補完・ブランチ名表示 メモ(2013.11)

git-completionの設定メモ

以前設定したときのメモはこちら
ネタ帳 A.B.C: Git 補完・ブランチ名表示 メモ
http://neta-abc.blogspot.jp/2013/02/git.html

環境

Mac OS X Maverics
Xcode 5.0.1
Git version 1.8.3.4 (Apple Git-47)
(GitはXcode付属のものを使う)

git-completion.bash/git-prompt.shのコピー

下記の2ファイルをホームディレクトリにリネームしてコピーする。
cp /Applications/Xcode.app/Contents/Developer/usr/share/git-core ~/.git-completion.bash
cp /Applications/Xcode.app/Contents/Developer/usr/share/git-core ~/.git-prompt.sh

.bash_profileの設定
if [ -f ~/.git-completion.bash ]; then
    source ~/.git-completion.bash
fi

if [ -f ~/.git-prompt.sh ]; then
    source ~/.git-prompt.sh
fi

PS1='\[\033[32m\]\u@\h\[\033[00m\]:\[\033[34m\]\w\[\033[31m\]$(__git_ps1)\[\033[00m\]\$ '

動作確認

下記のコマンドで.bash_profileを再読み込みする。
. .bash_profile

Gitで管理されたディレクトリに移動するとブランチ名が表示され、Gitのコマンド補完が効くようになる。

2013年9月30日月曜日

AndroidのlargeHeap(オレと皆さま調べ)

手持ちの端末+αでlargeHeap有効時のヒープサイズを調べてみました。

結果

まずは結果から。
こんな感じ。

[2016/06/03 3機種追加]
今回の追加分は@_postNogenoraさんに情報提供いただいたNexus 6/SBM104SHと
手持ちのSC-05G。
ありがとうございます!

MODEL API Level getMemoryClass() getLargeMemoryClass() ご協力
Nexus
Nexus 6 23 256MB 512MB @_postNogenoraさん
Nexus 10 17 192MB 512MB オレ
Nexus 7(2013) 18 192MB 512MB @kimukou2628さん
Nexus 7(2012) 18 64MB 384MB オレ
Nexus 5 19 192MB 512MB オレ
Nexus 4 18 192MB 512MB オレ
Galaxy Nexus 17 96MB 256MB オレ
Nexus S 16 48MB 128MB オレ
docomo
SC-05G 23 256MB 512MB オレ
F-05F 19 192MB 512MB @wakuimasashiさん
SH-04F 19 128MB 384MB @wakuimasashiさん
SH-05F 17 128MB 384MB @wakuimasashiさん
SO-04E 16 128MB 384MB オレ
SO-03E 16 128MB 384MB オレ
SO-02E 16 128MB 384MB オレ
SH-04E 16 64MB 256MB オレ
F-10D 15 72MB 256MB オレ
SO-05D 15 64MB 256MB オレ
SO-03D 15 64MB 256MB オレ
N-02E 15 64MB 256MB @takkeさん
SC-06D 15 64MB 256MB @kimukou2628さん
SO-01F 17 192MB 512MB オレ
F-01F 17 128MB 384MB オレ
SC-01F 18 128MB 512MB オレ
L-01F 17 128MB 256MB オレ
F-07E 17 128MB 384MB オレ
L-05E 17 96MB 256MB オレ
SH-07E 17 64MB 256MB オレ
N-06E 17 128MB 384MB オレ
SH-06E 17 128MB 384MB オレ
SC-04E 17 128MB 512MB オレ
HW-03E 16 256MB 256MB オレ
L-04E 16 128MB 256MB オレ
dtab01 16 256MB 256MB オレ
P-02E 16 128MB 384MB オレ
F-03E 15 72MB 256MB オレ
SH-02E 15 64MB 256MB オレ
HW-01E 15 128MB 256MB オレ
SO-01E 16 64MB 256MB オレ
SH-01E 15 54MB 160MB オレ
P-08D 15 48MB 256MB オレ
SH-10D 15 64MB 256MB オレ
F-11D 15 84MB 128MB オレ
L-06D 15 70MB 256MB オレ
T-02D 15 72MB 256MB オレ
N-07D 15 64MB 256MB オレ
L-05D 15 64MB 256MB オレ
SH-09D 15 64MB 256MB オレ
F-09D 15 72MB 128MB オレ
SH-07D 15 48MB 128MB オレ
SC-05D 15 64MB 256MB オレ
au
SOL25 19 143MB 463MB @wakuimasashiさん
SCL23 19 128MB 512MB @wakuimasashiさん
SOL23 17 192MB 512MB オレ
SCL22 18 128MB 512MB オレ
SHL22 17 64MB 256MB オレ
KYY21 17 96MB 256MB オレ
HTL22 16 192MB 384MB オレ
SOL22 17 192MB 512MB @hikaru__mさん
SOL22 16 128MB 384MB オレ
HTL21 16 128MB 256MB @takkeさん
SCL21 15 64MB 256MB オレ
FJL21 15 72MB 256MB オレ
IS17SH 15 54MB 160MB オレ
ISW16SH 15 64MB 256MB オレ
IS15SH 15 54MB 160MB オレ
ISW13HT 15 48MB 128MB オレ
IS12S 15 64MB 256MB @takkeさん
IS11LG 15 64MB 64MB オレ
ISW11SC 15 64MB 256MB オレ
ISW11F 15 72MB 256MB オレ
URBANO PROGRESSO 15 64MB 256MB オレ
SoftBank
SBM107SH 15 64MB 256MB オレ
SBM104SH 15 64MB 256MB @_postNogenoraさん

IS11LGはlargeHeap有効時もヒープサイズは増えないようです。
IS11LGだけなのか、他にも同様の端末があるのか分かりませんがリファレンスをみると

ActivityManager | Android Developers http://developer.android.com/reference/android/app/ActivityManager.html#getLargeMemoryClass()

This may be the same size as getMemoryClass() on memory constrained devices
とあるので、許容動作の模様。

コード

検証用のコードは、こんな感じ。
package com.tytosoft.largeheapchecker;

import android.app.Activity;
import android.app.ActivityManager;
import android.os.Build;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
        String info = "MODEL : " + Build.MODEL + "\n"
                + "API Level : " + Build.VERSION.SDK_INT + "\n"
                + "getMemoryClass() : " + activityManager.getMemoryClass() + "MB\n"
                + "getLargeMemoryClass() : " + activityManager.getLargeMemoryClass() + "MB";

        TextView textView = (TextView) findViewById(R.id.textview);
        textView.setText(info);
    }

}

getMemoryClass() : largeHeap無効時のヒープサイズ
getLargeMemoryClass() : largeHeap有効時のヒープサイズ
だと思っている。

アプリ

検証に使ったアプリをGoogle Playにアップしてみました。

Get it on Google Play

largeHeapはAPI Level 11から使えますが、3.xタブレットはもう考慮しなくて良いと思っているのでminSdkVersionは14としています。

お手持ちの端末で動かしたスクリーンショットなどをこちらまで送っていただければ、上記の表に追加したり、しなかったりします。

2013年9月29日日曜日

Androidでパスワード付きZipファイルを展開する方法

2013/11/09 In-Memoryで捌く方法を追記

ライブラリ

Zip4jというライブラリを使用します。
Zip4j - Java library to handle Zip files
http://www.lingala.net/zip4j/

Zip4jのライセンスはApache License, Version 2.0。
Zip4j - About
http://www.lingala.net/zip4j/about.php

プロジェクトにライブラリを追加

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:0.5.+'
    }
}
apply plugin: 'android'

repositories {
    mavenCentral()
}

android {
    compileSdkVersion 18
    buildToolsVersion "18.0.1"

    defaultConfig {
        minSdkVersion 7
        targetSdkVersion 18
    }
}

dependencies {
    compile 'net.lingala.zip4j:zip4j:1.3.1'
}

build.gradleにライブラリを追加する時は、こちらのサイトが便利です。
Gradle, please
http://gradleplease.appspot.com/

Zip4jで検索するとこんな感じに表示されますので、あとはbuild.gradleにコピペすればOKです。

Eclipseで開発している場合は下記のページからjarファイルをダウンロードしてlibsディレクトリに配置します。
Zip4j - Java library to handle Zip files
http://www.lingala.net/zip4j/download.php

サンプルコード

package com.example.passzip;

import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;

import net.lingala.zip4j.core.ZipFile;
import net.lingala.zip4j.exception.ZipException;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        String zipFilePath = Environment.getExternalStorageDirectory().getPath() + "/PassZip/hoge.zip";
        String destinationPath = Environment.getExternalStorageDirectory().getPath() + "/PassZip/";
        String password = "hoge";
        try {
            ZipFile zipFile = new ZipFile(zipFilePath);
            if (zipFile.isEncrypted()) {
                zipFile.setPassword(password);
            }
            zipFile.extractAll(destinationPath);
        } catch (ZipException e) {
            e.printStackTrace();
        }
    }

}
sdcard/PassZip/ディレクトリにあるパスワード付きZipファイルhoge.zipを同じディレクトリに展開するサンプルになっています。
Zipファイルの中身はfoo.txtが入ったhogeディレクトリです。
Zipファイルのパスワードはhogeとします。
外部ストレージに書き込みを行いますのでマニフェストファイルに
android.permission.WRITE_EXTERNAL_STORAGE
の宣言が必要です。

サンプルコードでは簡略化のため、UIスレッド上でZipの展開処理を行っています。
実際にアプリで使用する場合はAsyncTaskなどを使ってUIスレッドをブロックしないようにします。
エラー処理も省略していますので適宜エラー処理を行います。

動作確認

動作確認は
・Xperia Z(Android OS 4.1.2)
・IS14SH(Android OS 2.3.5)
で行いました。

アプリ実行前
アプリ実行後
実機のファイラーアプリからfoo.txtを確認したところ、テキストファイルの内容が表示されましたので正常にパスワード付きZipファイルの展開が行われているようです。

In-Memory(2013/11/09 追記)

上記のサンプルではZipファイルをストレージに展開してから使用しましたが、In-Memoryで捌く方法はこんな感じです。
このサンプルではgetExternalFilesDir()なディレクトリにある、test.zipの中身(ic_launcher.png)を読み込んでImageViewに表示しています。

ZipFile zipFile = null;
FileHeader fileHeader = null;
InputStream inputStream = null;
Bitmap bitmap = null;
try {                                                                         
    zipFile = new ZipFile(getExternalFilesDir(null).getPath() + "/test.zip");
    if (zipFile.isEncrypted()) {                                              
        zipFile.setPassword("password");                                      
    }                                                                         
    String filePath = "ic_launcher.png"; // アーカイブ内のファイルパス                     
    fileHeader = zipFile.getFileHeader(filePath);                             
    inputStream = zipFile.getInputStream(fileHeader);                         
    bitmap = BitmapFactory.decodeStream(inputStream);                         
    inputStream.close();                                                      
} catch (ZipException e) {                                                    
    // TODO: error handling                                                   
} catch (IOException e) {                                                     
    // TODO: error handling                                                   
}                                                                             
                                                                              
ImageView imageView = (ImageView) findViewById(R.id.image_view);              
imageView.setImageBitmap(bitmap);                                             

参考サイト

こちらのサイトを参考にさせていただきました。
ありがとうございます。
shinodogg.com
パスワード付きZipファイルをJava(Zip4j)で
http://shinodogg.com/?p=4601

2013年9月6日金曜日

Android StudioでGit(core.autocrlf)


Android Studioで作ったプロジェクトをコミットするときに出た、警告ダイアログの対処メモ。

環境

・Mac OS X 10.8.4
・Android Studio (I/O Preview) 0.2.6

原因

Android Studioのデフォルト設定では下記の
[Warn if CRLF line separators are about to be committed]
にチェックが入っている。
CRLFラインセパレータがコミットされようとしている場合に警告を表示するという設定。
core.autocrlfが未設定だったり、falseに設定されていると上記の警告ダイアログが表示される。

CRLFラインセパレータなファイルとはgradlew.bat。
gradlew.batをエディタで開いてステータスバーを確認すると確かにCRLFとある。
Windows環境で使うファイルですからね。

core.autocrlfとは

コミット時の改行コードの扱いを決めるもののようです。

こちらのサイトを参考にさせていただきました。
WindowsやMacなど様々なOSからGitを使うときの改行コードの扱い » tech-tec
http://tech-tec.com/archives/107

対処

冒頭のダイアログにもありますが
git config --global core.autocrlf input
の設定を行うと解決します。

コマンドラインから上記コマンドを実行して、コミットを行ってもよいですし
冒頭のダイアログで[Fix and Commit]ボタンをクリックすると自動でcore.autocrlfをinputに設定した後、コミットを行ってくれます。

core.autocrlfの設定確認

<User Home>/.gitconfigをテキストエディタで開く
or
ターミナルからgit config -l コマンドで確認できる。