最終更新 2024.04.01
この例は、デフォルトではないドライブにインストールするときの 覚え書きである。 http://thinkit.co.jp/story/2015/02/26/5646/page/0/1 http://thinkit.co.jp/story/2015/02/26/5646/page/0/2 に書いてある通りに行う。 1. Oracle のサイトに行って JDK 8 Update 60 (64bit) をインストールする。 インストール先は d ドライブに変更する。 d:\Program Files\Java\jdk1.8.0_60 d:\Program Files\Java\jre1.8.0_60 2. Android Studio のインストール インストール先は以下のように変更する。 android studio: d:\Program Files\Android\Android Studio (500MB) android SDK: d:\(user-home)\AppData\Local\Android\sdk (3.2GB) インストールの途中で、以下のエラーダイアログが表示される。 Failed to install Intel HAXM. For details, please check the instllation log: "C:\(user-home)\AppData\Local\Temp\nso4191.tmp\haxm_silent_run.log" この結果として、エミュレータが動かない。対処法は後で示す。 3. Android Studio の起動 1 回目の起動はものすごく時間がかかる(5 分以上) 待ちきれずに、「動かない」と思わないように。
環境変数 JAVA_HOME を設定する。 C:\Program Files\Java\jdk1.x.y_zz コマンドプロンプトで > echo %JAVA_HOME% で確認できる。
2 つ原因がある。 1. Intel のハードウェアアクセラレータが on になっていない。 2. エミュレータがインストールされていない。 1. は bios の設定変更が必要。 起動時に del キーを押すと、bios 設定モードに入る。 マウス操作可能。 (職場のパソコン) 右上の advanced 設定モード -- Advanced -- CPU configuration -- intel virualization → enabled (自宅のパソコン) advanced settings -- cpu settings -- intel visualization technology → enabled f10 で抜ける 2. は以下の手順が必要。 file -- settings -- appearance & behavior -- system settings -- android sdk --- SDK Tools -- 下から 2 番目の Intel x86 emulator accelerator で「インストーラ」をインストールする。 次に、その「インストーラ」を起動して「エミュレータ」をインストールする。 インストーラの位置は以下の通り。 (ユーザーフォルダ)\AppData\Local\Android\sdk\extras\intel \Hardware_Accelerated_Execution_Manager\intelhaxm-android.exe
File -- Settings -- Editor -- Colors & Fonts まず scheme save as をクリックする。そうでないと、 変更できない。 フォント:Font 16pt 色: use interited attributes にチェックが入っている色は、 先祖の設定を受け継ぐ。 General -- Text -- Default Text をまず設定する。 次に Language Defaults を設定する。 次に Java を設定する。 コード例が表示されている領域でクリックすると、 その部分に該当する部分の色を設定することができる。 プロジェクトビュー、などの色は、Apply を押しても変わらない。 一旦 Android Studio を終了し、再度起動すると、変更されている (2015)。
・起動直後の操作 エミュレートする機種によっては、起動直後にまず、 鍵を外す動作をせねばならない。そうしないと、 いつまで待っても画面が進まない。 ・画面サイズの変更 Run --> Edit Configulations --> Android Application --> App General: Target Device を Emulator にして何か選ぶ Emulator: Additional command line options に -scale 0.8 ・画面がウィンドウの外にはみ出してしまったとき クリック --- alt + space --- M --- カーソル移動キー
C:\users\(user-name) の下に (1) .android 1.5G (2) .AndroidStudio1.3 500MB エディタの色設定情報はここにある (3) .gradle 20MB (4) AndroidStudioProjects 40MB というフォルダが作成され、ディスクを圧迫している。移動する。 (4) AndroidStudioProjects ユーザーが作るプログラムが入るフォルダである。 新規作成時に指定するフォルダを変更すればよい。 (2) .AndroidStudio1.3 (参考) http://www.laurivan.com/android-studio-change-the-location-of-androidstudiobeta/ D:\Program Files\Android\Android Studio\bin\idea.properties を書き換える。 idea.config.path=d:\(user-home)/.AndroidStudio1.3/config idea.system.path=d:\(user-home)/.AndroidStudio1.3/system (1)(2) .android .gradle (参考) http://stackoverflow.com/questions/2841766/possible-to-change-where-android-virtual-devices-are-saved シンボリックリンクを貼れば良いと書いてある http://qiita.com/opengl-8080/items/c2b6a93dfca5b61f9e6a シンボリックリンクの作成法 http://answers.microsoft.com/ja-jp/windows/forum/windows_7-windows_programs/windows-7/efef116a-2ea7-43f5-ac06-f553737870fa?auth=1 管理者権限で cmd を実行する方法 Windows にはハードリンク、シンボリックリンクの機能がある (今日、知った。Vista 以降に追加されたそうだ)。 シンボリックリンクはエクスプローラで見ると、ショートカットと同一に見えるが、 コマンドプロンプトで dir コマンドを実行すると、異なる。 スタートメニューで cmd と打って ctrl + shift + enter を押すと 管理者権限で cmd を実行する。 > d: > cd \(user-home) > mklink /d .android d:\(user-home).android > mklink /d .gradle d:\(user-home)\.gradle でシンボリックリンクを作成する。 後から振り返ると (1)〜(4) の全てが、この方法で解決可能であった。 (4) についてもシンボリックリンクを作成した。AppData もこの方法で 移動できると思われる。 別の方法として、環境変数を以下のように設定する方法でもいけるようだ。 set ANDROID_AVD_HOME=d:\(user-home)\.android\avd set GRADLE_USER_HOME=d:\(user-home)\.gradle
左端の Project をクリックすると、ツリー構造が見える。 ソースコード app -- src -- main -- java -- com.example.yabu.... 画面 app -- src -- main -- res -- layout -- activity_main.xml
・PC 側の操作 ドライバのインストールが必要。 Nexus, Xperia はドライバが自動でインストールされた。 Regza (T-01D) は富士通のサイトからドライバをダウンロードして インストールする必要があった。 Huawei MediaPad M1 8.0 は google のサイトからドライバをダウンロードして インストールする必要があった。 Huawei MediaPad M1 8.0 のドライバのインストール方法 - google で Huawei MediaPad M1 8.0 driver で検索 - http://mobileresources.biz/240-huawei-mediapad-m1-android-usb-driver-latest-version.html でドライバーがダウンロードできそうだが、ファイル PdaNetA4150.exe が見あたらない。 - google で PdaNetA4150.exe を検索 - 見つかったファイルをダウンロードして実行。 ・実機側の操作 Xperia, Regza (Android 2.x) 設定 → アプリケーション → 提供元不明のアプリ ○ 設定 → アプリケーション → 開発 → USB デバッグ ○ Nexux, Huawei での操作 (Android 4.x) 設定 -- 端末情報 -- ビルド番号を 7 回タップ -- 開発者向けオプション -- USB デバッグ ・Android Studio の操作 Run --> Edit Configulations --> General: Target Device = USB エミュレータの設定をしていない状態で Huawei を使う場合、 Tools --> Android --> Enable ADB Integration を on にする必要がある。 Run してから 8 秒くらいで実機での実行が始まる。 実機での終了は「戻る」ボタン。 実行できたということは、既にアプリはインストールされている。 ・Android のバージョンの違いによるエラー Xperia で実行しようとしたところ、 [INSTALL_FAILED_OLDER_SDK] というエラーが出た。Android 4.4 で作ったアプリを Android 2.3.4 で実行 しようとしたためである。Android のバージョンは最初のプロジェクトを作る 場所で決まるので、2.3 用のアプリを新規作成すると、実行できた。
「前回開いていたプロジェクトを開く」or「プロジェクトを選ぶ」 のどちらにするかは、以下の場所にある。 File --- Settings --- Appearance & Behavior --- System Settings --- Startup/Shutdown --- reopen last project on startup
全てを 1 から書かなくてはならない。 また、レイアウトエディタは使えない。 次の 3 つが必要である。 (1) Activity クラスを継承したクラス MyActivity (名前はこれでなくてもよい) を作成する。 (2) View クラスを 1 つ作成し、メイン Activity の onCreate メソッドの中で setContentView(new MyView(this)); のように呼ぶ。 (3) AndroidManifext.xml に以下の行を追加する。 これを怠ると no default Main Activity というエラーが出る。 activity タグの android:name=".xxxxx" の部分で main 関数に 相当するクラスの名前を定義しているようだ。 <application android:allowBackup="true" android:label="@string/app_name" android:icon="@mipmap/ic_launcher" android:theme="@style/AppTheme"> /*------- ここから ------*/ <activity android:name=".MyActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> /*------- ここまで ------*/ </application> 1 文字でもスペルミスをすると no fefault main activity というエラーが出る。例えば、 <category android:name="android.intend.category.LAUNCHER" /> となっていると (intend --> intent)、エラーが出て実行できない。 ボタンやエディットテキストなどのウィジェットを使うには、 自力で「配置、フォントサイズ設定」のコードを書かねばならない。
Hello とだけ表示するノッペラボウのアプリが作成される。 アプリの構造は以下のようになっている。 ApplicationTest.java ApplicationTestCase<Application> クラスを継承して ApplicationText クラスを定義 MainActivity.java AppCompatActivity クラスを継承して MainActivity クラスを定義 AndroidManifest.xml より抜粋 <activity android:name=".MainActivity" ApplicationText クラスの役割については、よくわからない。
・プロジェクトのツリー構造 左端の「プロジェクト」をクリックすると、ツリー構造の ウィンドウが現れる。 ・レイアウトエディタ activity_main.xml (app -- src -- main -- res -- layout) をクリックすると、レイアウトエディタが起動する。 2 つのモードがある。 「左側にレイアウト 右側にプロパティリスト」 「左側に xml コード 右側にレイアウト」 左下の「Design」「Text」のタブで切り替える。 レイアウトが表示されないときは、右端の「Preview」をクリックする。
AndroidManifest.xml にネットワークのパーミッションを追加する。 </application> <uses-permission android:name="android.permission.INTERNET"></uses-permission> </manifest> android 3.0 以降は UI からネットワーク通信は不可である。 スレッドを作成し、その中からソケット通信を行う。 ------- サンプルプログラム --------- try{ Socket s = new Socket(ip_address, iport_no); BufferedWriter w = new BufferedWriter(new OutputStreamWriter(s.getOutputStream())); BufferedReader r = new BufferedReader(new InputStreamReader(s.getInputStream())); w.write(send_str.toString()); w.flush(); // これを忘れてはいけない recv_str = ""; String buf; while(true){ buf = r.readLine(); if ( buf == null ) break; recv_str = recv_str + buf + "\n"; } w.close(); r.close(); s.close(); ---------------------------------------------------------- 上の例で send_str = "1\n"; としたとき、1 の次は 0a が送られる。0d 0a ではない。
ソケット通信を行うスレッドから MainAcitivity のウィジェットを 操作しようとするとエラーが発生する。Android では UI の操作を スレッドから行うことは禁止されているらしい。 ハンドラーを使う必要がある。 メイン UI のコード import android.os.Handler; クラス変数宣言部 static Handler handler; static TextView tv; onCreate の中 handler = new Handler(); tv = (TextView) findViewById(R.id.textview); スレッド内のコード final String msg = "moji retsu"; MainActivity.handler.post(new Runnable() { public void run() { MainActivity.tv.append(msg); // UI オブジェクトへの代入 } });
背景色 background foreground は設定しない 文字色 textColor 文字サイズ textSize (注意!) button.setWidth(int) が効かないことがある。これは、レイアウトエディタで不要な 設定が入っており、それがが優先される結果として生じる。 レイアウトエディタ上でドラッグすると、不要な設定が 書き込まれることがある。 layout:alignStart layout:toEndOf layout:toStartOf は不要なので、消す。
import android.widget.TextView; TextView tv; tv = (TextView) findViewById(R.id.textview); > 主なメソッド tv.setText("aaa\n"); tv.append("abc"\n"); tv.setTextColor(Color.rgb(255,0,0)); > 内容の取得 String str = tv.getText().toString(); > エディットできるようにする editable enabled focusable focusableInTouchMode > その他のメソッド setTextSize(10.0f); // dp setLineSpacing(float add, float mult); mult 倍され、さらに add が加算される。 setVerticalScrollerEnabled(true);
import android.widget.Button; import android.view.View; Button button1; button1 = (Button) findViewById(R.id.button); tv = (TextView) findViewById(R.id.textView); button1.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { tv.append("clicked!"); } });
main のクラスで static 宣言すると、 MainActivity.textview1 = のようにグローバル変数のように扱える。 また、どこでも button1 = (Button) findVIewById(R.id.button); とすると、オブジェクトへのポインタを取得できるので、 R.id.xxx がグローバル変数のような働きをするように見える。
activiti_main.xml を使っている場合は以下の通り。 1. レイアウトに id が付いていないので、id を設定する。 2. 以下のコードでサイズが取得できる (a) クラスの変数宣言部 RelativeLayout layout; int dpi, width, width2, height; double bairitu; (b) OnCreate の中 layout = (RelativeLayout) findViewById(R.id.layout); WindowManager wm = getWindowManager(); Display d = wm.getDefaultDisplay(); DisplayMetrics dm = new DisplayMetrics(); d.getMetrics(dm); bairitu = dm.density; // 倍率 : dp × 倍率 = px dpi = dm.densityDpi; // dpi (c) onWindowFocusChanged をオーバーライド public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); width = layout.getWidth(); height = layout.getHeight(); width2 = width - (int)(16 * 2 * bairitu); button1.setWidth( width2 / 2 ); } ここでの height は画面上部の「インジケータ用領域」 「アプリの名前を表示する帯状領域」は含まない。 アプリが使用する領域は width, height からレイアウトの padding × 2 を 引いた値である。 activity_main.xml の中を見ると、RelativeLayout に対して android:paddingLeft="@dimen/activity_horizontal_margin" とある。adtivity_horizonal_margin は app -- src -- main -- res -- values -- dimens.xml の中にあり、16dp となっている。 (d) dp, px, mm, pt の変換 dp <--> px dm.density で得られた倍率を用いる dp × 倍率 = px px <--> mm px ÷ dpi × 25.4 = mm dp <--> pt 1 inch = 2.54 cm = 72 pt ex. 倍率 2 倍, 320 dpi, 横幅 800 px のとき 横幅の px = 800 - 16×2×2 = 736 px ex. 倍率 1.5 倍, 240 dpi, 横幅 480 px のとき 横幅の px = 480 - 16×1.5×2 = 432 px ex. 320 dpi, 倍率 2 のとき 20, 24, 28 dp のフォントは 20 × 2 ÷ 320 × 72 = 9 pt 24 × 2 ÷ 320 × 72 = 10.8 pt 28 × 2 ÷ 320 × 72 = 12.6 pt ex. 240 dpi, 倍率 1.5 のとき 20, 24, 28 dp のフォントは 20 × 1.5 ÷ 240 × 72 = 9 pt 24 × 1.5 ÷ 240 × 72 = 10.8 pt 28 × 1.5 ÷ 240 × 72 = 12.6 pt
layout:alignparent 1 つ上の階層のコンポーネントに合わせる TextView は left と right にチェックを入れることが多い。 layout:aligncomponent 同一階層のコンポーネントからの相対位置 bottom:top xxxx 自分の下端を xxxx の上端に合わせる top:bottom yyyy 自分の上端を yyyy の下端に合わせる left:right zzzz 自分の左端を zzzz の上端に合わせる layout:margin 上で指定したコンポーネントとの間隔 並べ替え ドラッグしても大抵はうまくいかない。 layout:aligncomponent で設定する。 左下のタブを「Design」から「Text」に切り替えて編集する方法もある。
typeface monospace 使用時 単位 dp 目視で確認 textsize 行送り 横幅 24 28.5 (1.1875) 14.5 (0.604166) 20 24 (1.2 ) 12 (0.6) 16 19 (1.1875) 9.5 (0.59375) 横幅はこれより 0.1dp でも小さくなると、次の行へ送られる。 自動改行の場合、縦幅はこれよし少し小さかったり大きかったりした場合、 行間が自動的に伸び縮みする。
レイアウトに id (この例では layout) をつける layout = (RelativeLayout) findViewById(R.id.layout); TextView tv = new TextView(); // コンストラクタ tv.setWidth(500); tv.setHeight(500); .... 色々な設定 layout.addView(tv);
Textview tv; tv = (TextView) findViewById(R.id.textView); tv.setHeight(300); tv.setWidth(200); tv.measure(0,0); // https://gist.github.com/tuoxie007/10981189 // から引用。0,0 の意味はよくわからない // http://developer.android.com/reference/android/view/View.MeasureSpec.html // に書いてあるが・・・ width = tv.getWidth(); width2 = tv.getMeasuredWidth(); height = tv.getHeight(); height2 = tv.getMeasuredHeight(); とすると、 width 200 width2 よくわからない値 height activity_main.xml で設定した値 height2 300 となる。なぜこうなるのか謎。
このサイトに詳しくまとめられている。 http://yyyank.blogspot.jp/2013/01/android.html
Blank Activity の Relative Layout を使う。 Canvas を自作の 1 つの部品として製作し、配置する。 http://d.hatena.ne.jp/compound/20110803/1312377989 に書いてある。 1. Canvas のクラスを View を継承して作成する。 2. レイアウトエディタを Text モードにして、そのクラスを手作業で記述する。 一旦、レイアウトエディタが認識すれば、あとは普通の部品と同様に扱える。 1. のサンプル package com.example.yabu.drawtest; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; import android.view.View; /** * Created by yabu on 2015/10/02. */ public class GView extends View { int width, height, fontsize = 40, px, py; public GView(Context context, AttributeSet attrs){ super(context, attrs); setBackgroundColor(Color.rgb(213, 213, 213)); } @Override protected void onDraw(Canvas canvas){ width = getWidth(); height = getHeight(); Paint paint = new Paint(); paint.setColor(Color.rgb(255,0,0)); paint.setStrokeWidth(3); paint.setTextSize(fontsize); String str = new String(); str = "width = " + width + " height = " + height; canvas.drawText(str.toString(), 0, fontsize + 2,paint); canvas.drawLine(0, 0, width, height, paint); } } 2. のサンプル <com.example.yabu.drawtest.GView android:layout_width="fill_parent" android:layout_height="500dp" />
app --- res --- values --- styles.xml <style name="AppTheme" parent="Theme.AppCompat.NoActionBar">
app --- res --- values -- dimens.xml
Tools --- Android --- Android Device Monitor File Explore のタブをクリック ファイルをクリックして、右上の「Pull a file from the device」 をクリックすると、パソコンにコピーできる。
external storage に書き込んだものは、PC と USB 接続したとき、 読み書きできる。 Xperia では変更は逐一 PC から見えるドライブ内のファイルに反映される。 Nexux 7 では PC の USB ドライブから見えるファイルは、最新の状態ではない。 一旦 USB 接続を切り離して、再度接続すると、最新の状態になる。 あるいは Android Device Manager を使ってコピーすると最新の状態が得られる。 AndroidManifest.xml <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> ファイルへ書き込み sd_path = Environment.getExternalStorageDirectory().getPath(); fname = sd_path + "/time.txt"; try { FileOutputStream outs = new FileOutputStream(fname, true); // append BufferedWriter w = new BufferedWriter(new OutputStreamWriter(outs, "UTF-8")); w.write(strbuf.toString()); w.flush(); w.close(); outs.close(); } catch (FileNotFoundException e) { Log.e("FileNotFoundException", e.getMessage()); } catch (IOException e){ Log.e("IOException", e.getMessage()); } PC から見えるようにする。 MediaScannerConnection.scanFile(getApplicationContext(), new String[]{fname}, new String[]{"text/plain"}, null);
大部分は https://akira-watson.com/android/gps.html からの引用。 AndroidManifest.xml <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> MainActivity.java (1) import 部 import android.location.*; (2) クラス宣言, クラス変数 public class MainActivity extends AppCompatActivity implements LocationListener { private LocationManager locationManager; (3) onCreate() locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); final boolean gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); if ( gpsEnabled == false ) { Toast.makeText(this, "位置情報を on にして下さい。", Toast.LENGTH_LONG).show(); } (4) オーバーライドするメソッド setconsole は自作関数なので無視してください @Override protected void onResume() { setconsole("onResume"); if (locationManager != null) { // minTime = 1000msec, minDistance = 50m locationManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, 1000, 50, this); setconsole("locationManager is updated."); } super.onResume(); } @Override protected void onPause() { setconsole("onPause"); if (locationManager != null) { // update を止める locationManager.removeUpdates(this); } super.onPause(); } @Override public void onLocationChanged(Location location) { setconsole("onLocationChanged"); latitude = location.getLatitude(); // double longitude = location.getLongitude(); s_latitude = String.valueOf(latitude); // String s_longitude = String.valueOf(longitude); setconsole("N " + s_latitude + " E " + s_longitude); } @Override public void onProviderDisabled(String provider) { } @Override public void onProviderEnabled(String provider) { } @Override public void onStatusChanged(String provider, int status, Bundle extras) { setconsole("onStatusChanged"); switch (status) { case LocationProvider.AVAILABLE: setconsole("LocationProvider.AVAILABLE"); break; case LocationProvider.OUT_OF_SERVICE: setconsole("LocationProvider.OUT_OF_SERVICE"); break; case LocationProvider.TEMPORARILY_UNAVAILABLE: setconsole("LocationProvider.TEMPORARILY_UNAVAILABLE"); break; } }
参考サイト // http://seesaawiki.jp/w/moonlight_aska/d/%B2%C3%C2%AE%C5%D9%A5%BB%A5%F3%A5%B5%A1%BC%A4%CE%C3%CD%A4%F2%BC%E8%C6%C0%A4%B9%A4%EB public class MainActivity extends AppCompatActivity implements SensorEventListener { public TextView tv; public SensorManager sm; double ax, ay, az; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv = (TextView) findViewById(R.id.textView); sm = (SensorManager)getSystemService(SENSOR_SERVICE); ax = 0; ay = 0; az = 9.8; } @Override protected void onStop() { super.onStop(); sm.unregisterListener(this); } @Override protected void onResume() { super.onResume(); List<Sensor> sensors = sm.getSensorList(Sensor.TYPE_ACCELEROMETER); if (sensors.size() > 0) { Sensor s = sensors.get(0); sm.registerListener(this, s, SensorManager.SENSOR_DELAY_UI); } } @Override public void onSensorChanged(SensorEvent e) { double x_now, y_now, z_now; String str; if( e.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { x_now = fix_value(e.values[0]); y_now = fix_value(e.values[1]); z_now = fix_value(e.values[2]); if ( ax != x_now || ay != y_now || az != z_now ) { ax = x_now; ay = y_now; az = z_now; str = String.format("accel: x(%5.1f) y(%5.1f) z(%5.1f)",ax,ay,az); tv.setText(str); } } } //----------- 値を四捨五入する ---------- public double fix_value(double in) { int keta = 1; // 小数点以下何桁目まで有効にするか double multi, ret; multi = Math.pow(10,keta); ret = Math.round(in * multi) / multi; return ret; } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; }