|
<Number>: [00000A4A]
<Date>: 2016/05/08 16:48:41
<Title>:
<Name>: amanojaku@管理人
|
|
|
ActionBarActivity が非推奨になったので、AppCompatActivity を作ってみたが、Dialog の UI Widget は古い Style のままなので AppCompatActivity の新しい Style の UI Widget とは UI に一貫性がない。
(他の方法がワカランので)非推奨の ActionBarActivity を使う事で とりあえずは古い Style の UI Widget に合わせられる。
《参考》
TextViewに枠線を付ける&背景色を変更する - yokkongの日記
http://d.hatena.ne.jp/yokkong/20111116/1321425474
【Android開発】スタイルにborderがないけど枠線を表示したい
http://se-suganuma.blogspot.jp/2010/02/androidborder.html
AppCompat
http://artemis.rosx.net/sjis/smt.cgi?r+izanami/&bid+0000090D&tsn+000009D3.&
とりあえず、[New Project]で(1ページ目)[Application name]:「Empty」、[Company domain]:[example.com]、[Project location]:「C:\Documents and Settings\<User名>\AndroidStudioProjects\<Application name>」と設定(<Application name>は[Application name]で設定した名前と全く同じにして下さい)、(2ページ目)[Phone and Tablet][Minimum SDK]:[API 8:Android 2.2]と設定、(3ページ目)(「Activity」とかもテキストで上書きしてしまうので)「Activity」の設定は とりあえず「Empty Activity」としておく。
『<Project名>→app→main→res→drawable-hdpi』フォルダー(存在しない場合は作成してやる)内に「Android SDK」のデフォルト・アイコン「ic_menu_moreoverflow_normal_holo_light.png」をコピーする。
一応、「アプリの Logo マーク」を Android のマスコット・キャラの「Droid君」にしている。
下の方に『<Project名>→app→main→res→drawable-hdpi』フォルダー用の画像ファイル「アプリの Logo マーク:「48x48」Pixel、その他"TextView"用アイコンをアップしてあります。
"drawable-mdpi"フォルダー用は手抜きして作ってないが、解像度が低い端末でも自動的に その端末の解像度に合うように縮小して表示される。
その場合、当然 画質は悪くなるので画質を綺麗にしたい場合は手抜きせずにチャント"drawable-mdpi"フォルダー用の画像ファイルを作成してやれば良い。
「Toolbar」の UI はスタンダードな「ActionBarActivity」のような感じになっている。
(合っているハズなのに)エラーが消えない場合は一旦 Project を閉じてから、ふたたび Project を開いてみて下さい。
『<Project名>→app→main→java→com.example.empty→MainActivity(MainActivity.java)』
package com.example.empty;
import android.os.Bundle;
import android.os.Build;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.KeyEvent;
import android.os.Environment;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.Context;
import android.content.res.Resources;
import android.content.Intent;
import android.app.PendingIntent;
import android.app.Activity;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.app.ActionBar;
import android.support.v7.widget.Toolbar;
// import android.widget.Toolbar;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends Activity implements
View.OnClickListener {
static final String fsDebugCrest = " 002";
static final String tag = "LogCat.Debug"; // フィルタリング用タグ。
// ↑ 分かりやすければ どんな文字列でも良い。
static final boolean DEBUG = true; // false; //
// ↑ この"DEBUG"は予約語では無い、"Java"において"final"(定数)の場合は
// 全部 大文字で記述するの事が推奨されているようだ。
// 「DEBUG=true」に設定すれば「if(DEBUG)Log.i(〜)」によって"LogCat"に出力される事になる。
DisplayMetrics oDisplayMetrics;
public static int iPhysicalWidth, iPhysicalHeight;
float vfDisplayMetricsDensity;
MainActivity oMainApp;
Context oBaseContext;
Context oAppContext; // Application Context.
Context oContext; // Activity Context.
String vsToolbarTitle;
Menu oMainMenu;
String vsPackageName;
String vsVersionName;
int iVersionCode;
TextView wtvMessage;
static final int[] WIDGETS = new int[]{
R.id.textView1, R.id.textView2,
R.id.button1, R.id.checkBox1, R.id.toggleButton1, R.id.radioButton1 };
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (DEBUG) Log.i(tag, "Activity.onCreate( );");
setContentView(R.layout.activity_main);
oMainApp = this;
// System 共通の Context:別の Application とやりとりするとき。
oBaseContext = getBaseContext();
// Application 固有の Context(Application ごとに Context が変化する):Application 共通のモノが対象。
oAppContext = getApplicationContext();
// Activity 固有の Context(Activity ごとに Context が変化する):Activity に依存モノが対象。
oContext = this;
oDisplayMetrics = oAppContext.getResources( ).getDisplayMetrics( );
vfDisplayMetricsDensity = oDisplayMetrics.density;
iPhysicalWidth = oDisplayMetrics.widthPixels;
iPhysicalHeight = oDisplayMetrics.heightPixels;
if (DEBUG) Log.i(tag, "Activity.onCreate( ) : " +
"vfDisplayMetricsDensity=" + vfDisplayMetricsDensity + "; " +
"iPhysicalWidth=" + iPhysicalWidth + "; " +
"iPhysicalHeight=" + iPhysicalHeight + "; " +
"");
vsPackageName = getPackageName();
try {
PackageInfo packageInfo = getPackageManager().getPackageInfo(
getPackageName(), PackageManager.GET_META_DATA);
// 「<Project名>→app→build.gradle」ファイル内の
// 「versionName、versionCode」の設定値を取得。
vsVersionName = packageInfo.versionName;
iVersionCode = packageInfo.versionCode;
} catch (NameNotFoundException e) {
e.printStackTrace();
}
wtvMessage = (TextView) findViewById(R.id.wtvMessage);
wtvMessage.append("fsDebugCrest=" + fsDebugCrest + ";\n" +
"PackageName=" + vsPackageName + ";\n" +
"VersionName=" + vsVersionName + ";\n" +
"RevisionNo=" + String.valueOf(iVersionCode) + ";\n" +
"vfDisplayMetricsDensity=" + vfDisplayMetricsDensity + ";\n" +
"iPhysicalWidth=" + iPhysicalWidth + ";\n" +
"iPhysicalHeight=" + iPhysicalHeight + "\n" +
"");
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.inflateMenu(R.menu.main);
toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
// メニューのクリック処理
if (DEBUG) Log.i(tag, "toolbar.onMenuItemClick( );");
return oMainApp.onOptionsItemSelected(item);
}
});
// actionbar.setIcon(R.drawable.ic_menu_info_details);
toolbar.setLogo(R.drawable.x_logo_android022);
// ↑ 実際は Logo マークはアプリ固有の Icon にすべきモノです。
// アプリ固有の Logo マークと言われてもイメージが湧かない方は
// ブラウザの Icon(Logo マーク)をイメージしてみて下さい。
// 下記サイトに主要ブラウザの Icon(Logo マーク)が掲載されています。
// http://freesoft-100.com/pasokon/browser.html
// ちなみに Toolbar に表示する Icon サイズのスタンダードは
// "drawable-mdpi"フォルダー用は「32x32」、
// "drawable-hdpi"フォルダー用は「48x48」だと思われます。
vsToolbarTitle = " " + getString(R.string.app_name) +
fsDebugCrest +
" V" + vsVersionName + // Version.
" R" + String.valueOf(iVersionCode); // Revision.
// ↑ Toolbar に Logo マークを表示させるとタイトルと Logo マークとの間に隙間がないので、
// タイトルの先頭に半角スペースを2つ入れている。
toolbar.setTitle(vsToolbarTitle);
for (int iWId : WIDGETS) {
View wvw = findViewById(iWId);
wvw.setOnClickListener(this);
}
}
@Override
protected void onRestart() {
super.onRestart();
if (DEBUG) Log.i(tag, "Activity.onRestart( );");
}
@Override
protected void onStart() {
super.onStart();
if (DEBUG) Log.i(tag, "Activity.onStart( );");
}
@Override
protected void onResume() {
super.onResume();
if (DEBUG) Log.i(tag, "Activity.onResume( );");
}
@Override
protected void onPause() {
super.onPause();
if (DEBUG) Log.i(tag, "Activity.onPause( );");
}
@Override
protected void onStop() {
super.onStop();
if (DEBUG) Log.i(tag, "Activity.onStop( );");
}
@Override
protected void onDestroy() {
super.onDestroy();
if (DEBUG) Log.i(tag, "Activity.onDestroy( );");
}
@Override
public void onClick(View v) {
// super.onClick(v);
if(DEBUG) Log.i(tag,"Activity.onClick( );");
switch(v.getId()) {
case R.id.textView1 :
if (DEBUG) Log.i(tag, "textView1");
break;
case R.id.textView2 :
if (DEBUG) Log.i(tag, "textView2");
break;
case R.id.button1 :
if (DEBUG) Log.i(tag, "button1");
break;
case R.id.checkBox1 :
if (DEBUG) Log.i(tag, "checkBox1");
break;
case R.id.toggleButton1 :
if (DEBUG) Log.i(tag, "toggleButton1");
break;
case R.id.radioButton1 :
if (DEBUG) Log.i(tag, "radioButton1");
break;
default :
if (DEBUG) Log.i(tag, "default");
return;
}
return;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
// アクションバー内で使用する為のメニューアイテムを実体化
MenuInflater inflater = getMenuInflater();
// MenuInflater inflater = getSupportMenuInflater();
inflater.inflate(R.menu.main, menu);
// 「R.menu.main」の「menu.main」は 恐らく「res」からの「フォルダー名+ファイル名」
oMainMenu = menu;
// 戻り値に true を返す事で Event が「消費された」事が通知され、
// 他の Event Listener の処理はキャンセルされます。
return true; // false; //
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
super.onOptionsItemSelected(item);
if(DEBUG) Log.i(tag,"Activity.onOptionsItemSelected( );");
switch(item.getItemId()) {
case R.id.menu_main_settings :
if (DEBUG) Log.i(tag, "menu_main_settings");
break;
case R.id.menu_main_settings_item1 :
if (DEBUG) Log.i(tag, "menu_main_settings_item1");
break;
case R.id.menu_main_settings_item2 :
if (DEBUG) Log.i(tag, "menu_main_settings_item2");
break;
case R.id.menu_main_settings_item3 :
if (DEBUG) Log.i(tag, "menu_main_settings_item3");
break;
default :
if (DEBUG) Log.i(tag, "default");
// 戻り値に false を返す事で Event は「消費されてない」事が通知され、
// 他の Event Listener の処理は継続されます。
return false; // true; //
}
// 戻り値に true を返す事で Event が「消費された」事が通知され、
// 他の Event Listener の処理はキャンセルされます。
return true; // false; //
}
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
super.dispatchKeyEvent(event);
if (DEBUG) Log.i(tag, "Activity.dispatchKeyEvent( );");
final int action = event.getAction();
final int keyCode = event.getKeyCode();
switch (keyCode) {
case KeyEvent.KEYCODE_MENU:
if (DEBUG) Log.i(tag, "KeyEvent.KEYCODE_MENU;");
if (action == KeyEvent.ACTION_UP) {
if (DEBUG) Log.i(tag, "KeyEvent.ACTION_UP;");
if (oMainMenu != null) {
if (DEBUG) Log.i(tag, "oMainMenu.performIdentifierAction( );");
oMainMenu.performIdentifierAction(R.id.menu_main_settings, 0);
}
// 戻り値に true を返す事で Event が「消費された」事が通知され、
// 他の Event Listener の処理はキャンセルされます。
return true; // false; //
}
break;
default:
if (DEBUG) Log.i(tag, "KeyEvent:Default");
break;
}
// 戻り値に false を返す事で Event は「消費されてない」事が通知され、
// 他の Event Listener の処理は継続されます。
return false; // true; //
}
}
『<Project名>→app→main→res→drawable→border.xml(ファイルを作成)』
※「UI Widget」の枠として使用する。
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#ffffff" />
<padding android:top="3dp" android:bottom="3dp"
android:left="7dp" android:right="7dp" />
<stroke android:width="1px" android:color="#000000" />
<corners android:radius="5dp" />
</shape>
『<Project名>→app→main→res→drawable→button_style.xml(ファイルを作成)』
※「TextView」をボタン・スタイルで表示させている。
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape android:shape="rectangle">
<solid android:color="@color/ButtonBackground"/>
<corners android:radius="3dp" />
<stroke android:width="2dp" android:color="@color/ButtonShadow" />
<!-- 「stroke android:width=」は ずらす幅より少し大きな値にする。 -->
</shape>
</item>
<item android:bottom="1.45dp" android:right="1.47dp">
<shape android:shape="rectangle">
<solid android:color="@color/ButtonBackground"/>
<padding android:top="4.4dp" android:bottom="4.4dp"
android:left="5dp" android:right="5dp" />
<corners android:radius="3dp" />
</shape>
</item>
</layer-list>
『<Project名>→app→main→res→layout→activity_main.xml』
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@color/white"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.ActionBar"
android:minHeight="?attr/actionBarSize"
android:background="@color/Background_Cornflowerblue"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_margin = "7dp"
android:background="@drawable/border" >
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="top"
android:textAppearance="?android:attr/textAppearanceLarge"
android:id="@+id/wtvMessage" />
</ScrollView>
<!-- ボタンは左右にムダなスペースがあるので、表示幅が Tight でボタンが表示できない場合、-->
<!-- TextView をボタン・スタイルで表示させれば良い。 -->
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textSize="22dp"
android:textColor="@color/black"
android:layout_marginTop = "6dp"
android:layout_marginBottom = "6dp"
android:layout_marginLeft = "3.5dp"
android:layout_marginRight = "3.5dp"
android:background="@drawable/button_style"
android:text="TextView1"
android:id="@+id/textView1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textSize="22dp"
android:textColor="@color/black"
android:layout_marginTop = "6dp"
android:layout_marginBottom = "6dp"
android:layout_marginLeft = "3.5dp"
android:layout_marginRight = "3.5dp"
android:background="@drawable/button_style"
android:drawableRight="@drawable/xic_menu_moreoverflow_focused_holo_light0272"
android:text="TextView2"
android:id="@+id/textView2" />
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:gravity="center">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textSize="22dp"
android:text="Button1"
android:id="@+id/button1" />
<ToggleButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textSize="22dp"
android:text="ToggleButton1"
android:id="@+id/toggleButton1" />
</LinearLayout>
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textSize="22dp"
android:text="CheckBox1"
android:id="@+id/checkBox1" />
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="22dp"
android:layout_gravity="center_horizontal"
android:text="RadioButton1"
android:id="@+id/radioButton1" />
</LinearLayout>
『<Project名>→app→src→main→res→menu→main.xml』(フォルダーとファイルを作成)
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity">
<item android:id="@+id/menu_main_settings"
android:title="Settings"
android:icon="@drawable/ic_menu_moreoverflow_normal_holo_light"
app:showAsAction="always">
<!-- ↑ showAsAction:Toolbar に対する表示設定。 -->
<!-- "always":常に表示、"never":常に表示しない、"ifRoom":表示する余裕があれば表示。 -->
<menu>
<item android:id="@+id/menu_main_settings_item1"
android:title="item1">
</item>
<item android:id="@+id/menu_main_settings_item2"
android:title="item2">
</item>
<item android:id="@+id/menu_main_settings_item3"
android:title="item3">
</item>
</menu>
</item>
</menu>
『<Project名>→app→src→main→res→values→colors.xml』
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryDark">#303F9F</color>
<color name="colorAccent">#FF4081</color>
<color name="holo_blue_light">#33b5e5</color>
<color name="Background_Cornflowerblue">#6495ED</color>
<color name="Background_MediumslateblueLike">#9b7fff</color>
<color name="ButtonBackground">#d7d7d7</color>
<color name="ButtonShadow">#c6c6c6</color>
<color name="GrayOutText001">#909090</color>
<color name="GrayOutText002">#888888</color>
<color name="GrayOutText003">#777777</color>
<color name="SettingMenuBackground">#eeeeee</color>
<color name="black">#000000</color>
<color name="gray">#808080</color>
<color name="silver">#c0c0c0</color>
<color name="white">#ffffff</color>
<color name="maroon">#800000</color>
<color name="red">#ff0000</color>
<color name="purple">#800080</color>
<color name="fuchsia">#ff00ff</color>
<color name="magenta">#ff00ff</color>
<color name="green">#008000</color>
<color name="lime">#00ff00</color>
<color name="olive">#808000</color>
<color name="yellow">#ffff00</color>
<color name="navy">#000080</color>
<color name="blue">#0000ff</color>
<color name="teal">#008080</color>
<color name="aqua">#00ffff</color>
<color name="cyan">#00ffff</color>
<color name="pink">#ffc0cb</color>
<color name="orange">#ffa500</color>
<color name="greenyellow">#adff2f</color>
<color name="yellowgreen">#9acd32</color>
</resources>
『<Project名>→app→main→AndroidManifest.xml』
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.empty">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme" >
<activity android:name=".MainActivity"
android:launchMode="singleInstance" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
|
|
|
<Number>: [00000A54]
<Date>: 2016/05/08 21:27:17
<Title>:
<Name>: amanojaku@管理人
|
|
|
内部ストレージの Path を取得する(外部ストレージの Path も取得できるハズだがテストはしてない)。
【android】 SDカードのpathを取得する方法 一番かんたんなJava入門
http://nobuo-create.net/sdcard-2/
> Environment.getExternalStorageDirectory()
> このメソッドを使えば、外部ストレージ(SDカード)のマウント先を簡単に取得することができていました。
> しかし、いつの頃からか、androidのとんでもない仕様変更により、この、名前からしていかにも外部ストレージのディレクトリをゲットしてくれそうな「Environment.getExternalStorageDirectory()」が、とんでもないトラップになってしまいました。それも結構悪質な。
> どんな悪質な罠か、結論からと申しますと、このメソッドで取得できるのは外部ストレージ(SDカード)のpathではなく、内部ストレージのpathなんです。
[Android] スマホのSDカードパスを取得、機種依存対策
https://akira-watson.com/android/sdcard_path.html
> if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD)
この条件からすると「Build.VERSION_CODES.GINGERBREAD(Android 2.3)」以降から仕様変更されたと思われます。
もし「Android 2.3」未満もサポートしたい場合は「Environment.getExternalStorageDirectory()」は使えないと言う事になるので、これらのサイトを参考にして「Environment.getExternalStorageDirectory()」を使わずに内部ストレージの Path を取得する。
《参考》
【android】 SDカードのpathを取得する方法 一番かんたんなJava入門
http://nobuo-create.net/sdcard-2/
[Android] スマホのSDカードパスを取得、機種依存対策
https://akira-watson.com/android/sdcard_path.html
アンドロイドのSDカードパスの取得方法 ≪ 大阪のアンドロイド-iOS・ Webアプリ開発会社 ノーティス
http://www.notice.co.jp/archives/3074
とりあえず、[New Project]で(1ページ目)[Application name]:「SDCard」、[Company domain]:[example.com]、[Project location]:「C:\Documents and Settings\<User名>\AndroidStudioProjects\<Application name>」と設定(<Application name>は[Application name]で設定した名前と全く同じにして下さい)、(2ページ目)[Phone and Tablet][Minimum SDK]:[API 8:Android 2.2]と設定、(3ページ目)(「Activity」とかもテキストで上書きしてしまうので)「Activity」の設定は とりあえず「Empty Activity」としておく。
『<Project名>→app→main→res→drawable-hdpi』フォルダー(存在しない場合は作成してやる)内に「Android SDK」のデフォルト・アイコン「ic_menu_moreoverflow_normal_holo_light.png」をコピーする。
一応、「アプリの Logo マーク」を Android のマスコット・キャラの「Droid君」にしている。
下の方に『<Project名>→app→main→res→drawable-hdpi』フォルダー用の画像ファイル「アプリの Logo マーク:「48x48」Pixel、その他"TextView"用アイコンをアップしてあります。
"drawable-mdpi"フォルダー用は手抜きして作ってないが、解像度が低い端末でも自動的に その端末の解像度に合うように縮小して表示される。
その場合、当然 画質は悪くなるので画質を綺麗にしたい場合は手抜きせずにチャント"drawable-mdpi"フォルダー用の画像ファイルを作成してやれば良い。
「Toolbar」の UI はスタンダードな「ActionBarActivity」のような感じになっている。
(合っているハズなのに)エラーが消えない場合は一旦 Project を閉じてから、ふたたび Project を開いてみて下さい。
『<Project名>→app→main→java→com.example.sdcard→MainActivity(MainActivity.java)』
package com.example.sdcard;
import android.os.Bundle;
import android.os.Build;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.KeyEvent;
import android.os.Environment;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.Context;
import android.content.res.Resources;
import android.content.Intent;
import android.app.PendingIntent;
import android.app.Activity;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.app.ActionBar;
import android.support.v7.widget.Toolbar;
// import android.widget.Toolbar;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity
implements View.OnClickListener {
static final String fsDebugCrest = " 001";
static final String tag = "LogCat.Debug"; // フィルタリング用タグ。
// ↑ 分かりやすければ どんな文字列でも良い。
static final boolean DEBUG = true; // false; //
// ↑ この"DEBUG"は予約語では無い、"Java"において"final"(定数)の場合は
// 全部 大文字で記述するの事が推奨されているようだ。
// 「DEBUG=true」に設定すれば「if(DEBUG)Log.i(〜)」によって"LogCat"に出力される事になる。
DisplayMetrics oDisplayMetrics;
public static int iPhysicalWidth, iPhysicalHeight;
float vfDisplayMetricsDensity;
MainActivity oMainApp;
Context oBaseContext;
Context oAppContext; // Application Context.
Context oContext; // Activity Context.
String vsToolbarTitle;
Menu oMainMenu;
String vsPackageName;
String vsVersionName;
int iVersionCode;
String vsDefaultSDCardRoot;
String vsExtensionSDCardRoot;
TextView wtvMessage;
static final int[] WIDGETS = new int[]{
R.id.textView1, R.id.textView2,
R.id.button1, R.id.checkBox1, R.id.toggleButton1, R.id.radioButton1 };
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (DEBUG) Log.i(tag, "Activity.onCreate( );");
setContentView(R.layout.activity_main);
oMainApp = this;
// System 共通の Context:別の Application とやりとりするとき。
oBaseContext = getBaseContext();
// Application 固有の Context(Application ごとに Context が変化する):Application 共通のモノが対象。
oAppContext = getApplicationContext();
// Activity 固有の Context(Activity ごとに Context が変化する):Activity に依存モノが対象。
oContext = this;
oDisplayMetrics = oAppContext.getResources( ).getDisplayMetrics( );
vfDisplayMetricsDensity = oDisplayMetrics.density;
iPhysicalWidth = oDisplayMetrics.widthPixels;
iPhysicalHeight = oDisplayMetrics.heightPixels;
SDCardOp.ScanSDCardRoot( );
vsDefaultSDCardRoot = SDCardOp.vsDefaultSDCardRoot;
vsExtensionSDCardRoot = SDCardOp.vsExtensionSDCardRoot;
if (DEBUG) Log.i(tag, "Activity.onCreate( ) : " +
"vfDisplayMetricsDensity=" + vfDisplayMetricsDensity + "; " +
"iPhysicalWidth=" + iPhysicalWidth + "; " +
"iPhysicalHeight=" + iPhysicalHeight + "; " +
"vsDefaultSDCardRoot=" + vsDefaultSDCardRoot + "; " +
"vsExtensionSDCardRoot=" + vsExtensionSDCardRoot + "; " +
"");
vsPackageName = getPackageName();
try {
PackageInfo packageInfo = getPackageManager().getPackageInfo(
getPackageName(), PackageManager.GET_META_DATA);
// 「<Project名>→app→build.gradle」ファイル内の
// 「versionName、versionCode」の設定値を取得。
vsVersionName = packageInfo.versionName;
iVersionCode = packageInfo.versionCode;
} catch (NameNotFoundException e) {
e.printStackTrace();
}
wtvMessage = (TextView) findViewById(R.id.wtvMessage);
wtvMessage.append("fsDebugCrest=" + fsDebugCrest + ";\n" +
"PackageName=" + vsPackageName + ";\n" +
"VersionName=" + vsVersionName + ";\n" +
"RevisionNo=" + String.valueOf(iVersionCode) + ";\n" +
"vfDisplayMetricsDensity=" + vfDisplayMetricsDensity + ";\n" +
"iPhysicalWidth=" + iPhysicalWidth + ";\n" +
"iPhysicalHeight=" + iPhysicalHeight + ";\n" +
"vsDefaultSDCardRoot=" + vsDefaultSDCardRoot + ";\n" +
"vsExtensionSDCardRoot=" + vsExtensionSDCardRoot + ";\n" +
"");
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ActionBar actionbar = getSupportActionBar();
// actionbar.setIcon(R.drawable.ic_menu_info_details);
actionbar.setLogo(R.drawable.x_logo_android022);
// ↑ 実際は Logo マークはアプリ固有の Icon にすべきモノです。
// アプリ固有の Logo マークと言われてもイメージが湧かない方は
// ブラウザの Icon(Logo マーク)をイメージしてみて下さい。
// 下記サイトに主要ブラウザの Icon(Logo マーク)が掲載されています。
// http://freesoft-100.com/pasokon/browser.html
// ちなみに Toolbar に表示する Icon サイズのスタンダードは
// "drawable-mdpi"フォルダー用は「32x32」、
// "drawable-hdpi"フォルダー用は「48x48」だと思われます。
vsToolbarTitle = " " + getString(R.string.app_name) +
fsDebugCrest +
" V" + vsVersionName + // Version.
" R" + String.valueOf(iVersionCode); // Revision.
// ↑ Toolbar に Logo マークを表示させるとタイトルと Logo マークとの間に隙間がないので、
// タイトルの先頭に半角スペースを2つ入れている。
actionbar.setTitle(vsToolbarTitle);
for (int iWId : WIDGETS) {
View wvw = findViewById(iWId);
wvw.setOnClickListener(this);
}
}
@Override
protected void onRestart() {
super.onRestart();
if (DEBUG) Log.i(tag, "Activity.onRestart( );");
}
@Override
protected void onStart() {
super.onStart();
if (DEBUG) Log.i(tag, "Activity.onStart( );");
}
@Override
protected void onResume() {
super.onResume();
if (DEBUG) Log.i(tag, "Activity.onResume( );");
}
@Override
protected void onPause() {
super.onPause();
if (DEBUG) Log.i(tag, "Activity.onPause( );");
}
@Override
protected void onStop() {
super.onStop();
if (DEBUG) Log.i(tag, "Activity.onStop( );");
}
@Override
protected void onDestroy() {
super.onDestroy();
if (DEBUG) Log.i(tag, "Activity.onDestroy( );");
}
@Override
public void onClick(View v) {
// super.onClick(v);
if(DEBUG) Log.i(tag,"Activity.onClick( );");
switch(v.getId()) {
case R.id.textView1 :
if (DEBUG) Log.i(tag, "textView1");
break;
case R.id.textView2 :
if (DEBUG) Log.i(tag, "textView2");
break;
case R.id.button1 :
if (DEBUG) Log.i(tag, "button1");
break;
case R.id.checkBox1 :
if (DEBUG) Log.i(tag, "checkBox1");
break;
case R.id.toggleButton1 :
if (DEBUG) Log.i(tag, "toggleButton1");
break;
case R.id.radioButton1 :
if (DEBUG) Log.i(tag, "radioButton1");
break;
default :
if (DEBUG) Log.i(tag, "default");
return;
}
return;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
// アクションバー内で使用する為のメニューアイテムを実体化
MenuInflater inflater = getMenuInflater();
// MenuInflater inflater = getSupportMenuInflater();
inflater.inflate(R.menu.main, menu);
// 「R.menu.main」の「menu.main」は 恐らく「res」からの「フォルダー名+ファイル名」
oMainMenu = menu;
// 戻り値に true を返す事で Event が「消費された」事が通知され、
// 他の Event Listener の処理はキャンセルされます。
return true; // false; //
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
super.onOptionsItemSelected(item);
if(DEBUG) Log.i(tag,"Activity.onOptionsItemSelected( );");
switch(item.getItemId()) {
case R.id.menu_main_settings :
if (DEBUG) Log.i(tag, "menu_main_settings");
break;
case R.id.menu_main_settings_item1 :
if (DEBUG) Log.i(tag, "menu_main_settings_item1");
break;
case R.id.menu_main_settings_item2 :
if (DEBUG) Log.i(tag, "menu_main_settings_item2");
break;
case R.id.menu_main_settings_item3 :
if (DEBUG) Log.i(tag, "menu_main_settings_item3");
break;
default :
if (DEBUG) Log.i(tag, "default");
// 戻り値に false を返す事で Event は「消費されてない」事が通知され、
// 他の Event Listener の処理は継続されます。
return false; // true; //
}
// 戻り値に true を返す事で Event が「消費された」事が通知され、
// 他の Event Listener の処理はキャンセルされます。
return true; // false; //
}
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
super.dispatchKeyEvent(event);
if (DEBUG) Log.i(tag, "Activity.dispatchKeyEvent( );");
final int action = event.getAction();
final int keyCode = event.getKeyCode();
switch (keyCode) {
case KeyEvent.KEYCODE_MENU:
if (DEBUG) Log.i(tag, "KeyEvent.KEYCODE_MENU;");
if (action == KeyEvent.ACTION_UP) {
if (DEBUG) Log.i(tag, "KeyEvent.ACTION_UP;");
if (oMainMenu != null) {
if (DEBUG) Log.i(tag, "oMainMenu.performIdentifierAction( );");
oMainMenu.performIdentifierAction(R.id.menu_main_settings, 0);
}
// 戻り値に true を返す事で Event が「消費された」事が通知され、
// 他の Event Listener の処理はキャンセルされます。
return true; // false; //
}
break;
default:
if (DEBUG) Log.i(tag, "KeyEvent:Default");
break;
}
// 戻り値に false を返す事で Event は「消費されてない」事が通知され、
// 他の Event Listener の処理は継続されます。
return false; // true; //
}
}
『<Project名>→app→main→java→com.example.sdcard→SDCardOp(SDCardOp.java)』
package com.example.sdcard;
import android.os.Build;
import android.os.Environment;
import android.util.Log;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Scanner;
import java.util.List;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class SDCardOp {
static final String tag = MainActivity.tag; // フィルタリング用タグ。
// ↑ 分かりやすければ どんな文字列でも良い。
static final boolean DEBUG = MainActivity.DEBUG;
// ↑ この"DEBUG"は予約語では無い、"Java"において"final"(定数)の場合は
// 全部 大文字で記述するの事が推奨されているようだ。
// 「DEBUG=true」に設定すれば「if(DEBUG)Log.i(〜)」によって"LogCat"に出力される事になる。
// SDCard が見つからない場合は Null になる。
public static String vsDefaultSDCardRoot;
public static String vsExtensionSDCardRoot;
public static void ScanSDCardRoot( ) {
if(DEBUG)Log.i(tag, "SDCardOp.getExpansionSDCardRoot( );");
// SDカードのマウント先をゲットするメソッド
vsDefaultSDCardRoot = null;
vsExtensionSDCardRoot = null;
Scanner scanner = null;
File file;
String path, sdcheck;
Pattern p;
Matcher m;
try {
// システム設定ファイルにアクセス
File vold_fstab = new File("/system/etc/vold.fstab");
// マウント情報を取得する
scanner = new Scanner(new FileInputStream(vold_fstab));
// 一行ずつ読み込む
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
if(DEBUG)Log.i(tag, "SDCardOp.getExpansionSDCardRoot( ) : "+
"line="+line+"; "+
"");
// 〜_mountで始まる行
p = Pattern.compile("^[a-zA-Z]+_mount");
m = p.matcher(line);
// なぜか「line.matches("^[a-zA-Z]+_mount")」では正常にチェックできなかった。
if ( m.find( ) ) {
// 半角スペースではなくタブで区切られている機種もあるらしいので修正して
// 半角スペース区切り3つめ(path)を取得
path = line.replaceAll("\t", " ").split(" ")[2];
if(DEBUG) Log.i(tag, "SDCardOp.getExpansionSDCardRoot( ) : "+
"path="+path+"; "+
"");
if ( isMounted(path) ){
sdcheck = path + "/.android_secure";
if (DEBUG) Log.i(tag, "SDCardOp.getExpansionSDCardRoot( ) : " +
"sdcheck=" + sdcheck + "; " +
"");
file = new File(sdcheck);
if ( file.exists( ) ) {
vsExtensionSDCardRoot = path;
}else{
vsDefaultSDCardRoot = path;
}
}
}
}
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} finally {
if (scanner != null) {
scanner.close();
}
}
return;
}
// 引数に渡したpathがマウントされているかどうかチェックするメソッド
public static boolean isMounted(String path) {
boolean isMounted = false;
Scanner scanner = null;
try {
// マウントポイントを取得する
File mounts = new File("/proc/mounts");
scanner = new Scanner(new FileInputStream(mounts));
// マウントポイントに該当するパスがあるかチェックする
while (scanner.hasNextLine()) {
if (scanner.nextLine().contains(path)) {
// 該当するパスがあればマウントされているってこと
isMounted = true; break;
}
}
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} finally {
if (scanner != null) {
scanner.close();
}
}
// マウント状態をreturn
return isMounted;
}
}
『<Project名>→app→main→res→drawable→border.xml』(ファイルを作成)
※「UI Widget」の枠として使用する。
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#ffffff" />
<padding android:top="3dp" android:bottom="3dp"
android:left="7dp" android:right="7dp" />
<stroke android:width="1px" android:color="#000000" />
<corners android:radius="5dp" />
</shape>
『<Project名>→app→main→res→drawable→button_style.xml』(ファイルを作成)
※「TextView」をボタン・スタイルで表示させている。
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape android:shape="rectangle">
<solid android:color="@color/ButtonBackground"/>
<corners android:radius="3dp" />
<stroke android:width="2dp" android:color="@color/ButtonShadow" />
<!-- 「stroke android:width=」は ずらす幅より少し大きな値にする。 -->
</shape>
</item>
<item android:bottom="1.45dp" android:right="1.47dp">
<shape android:shape="rectangle">
<solid android:color="@color/ButtonBackground"/>
<padding android:top="4.4dp" android:bottom="4.4dp"
android:left="5dp" android:right="5dp" />
<corners android:radius="3dp" />
</shape>
</item>
</layer-list>
『<Project名>→app→main→res→layout→activity_main.xml』
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@color/white"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
android:background="@color/Background_Cornflowerblue" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_margin = "7dp"
android:background="@drawable/border" >
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="top"
android:textAppearance="?android:attr/textAppearanceLarge"
android:id="@+id/wtvMessage" />
</ScrollView>
<!-- ボタンは左右にムダなスペースがあるので、表示幅が Tight でボタンが表示できない場合、-->
<!-- TextView をボタン・スタイルで表示させれば良い。 -->
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textSize="22dp"
android:textColor="@color/black"
android:layout_marginTop = "6dp"
android:layout_marginBottom = "6dp"
android:layout_marginLeft = "3.5dp"
android:layout_marginRight = "3.5dp"
android:background="@drawable/button_style"
android:text="TextView1"
android:id="@+id/textView1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textSize="22dp"
android:textColor="@color/black"
android:layout_marginTop = "6dp"
android:layout_marginBottom = "6dp"
android:layout_marginLeft = "3.5dp"
android:layout_marginRight = "3.5dp"
android:background="@drawable/button_style"
android:drawableRight="@drawable/xic_menu_moreoverflow_focused_holo_light0272"
android:text="TextView2"
android:id="@+id/textView2" />
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:gravity="center">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textSize="22dp"
android:text="Button1"
android:id="@+id/button1" />
<ToggleButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textSize="22dp"
android:text="ToggleButton1"
android:id="@+id/toggleButton1" />
</LinearLayout>
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textSize="22dp"
android:text="CheckBox1"
android:id="@+id/checkBox1" />
<RadioButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="22dp"
android:layout_gravity="center_horizontal"
android:text="RadioButton1"
android:id="@+id/radioButton1" />
</LinearLayout>
『<Project名>→app→src→main→res→menu→main.xml』(フォルダーとファイルを作成)
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity">
<item android:id="@+id/menu_main_settings"
android:title="Settings"
android:icon="@drawable/ic_menu_moreoverflow_normal_holo_light"
app:showAsAction="always">
<!-- ↑ showAsAction:Toolbar に対する表示設定。 -->
<!-- "always":常に表示、"never":常に表示しない、"ifRoom":表示する余裕があれば表示。 -->
<menu>
<item android:id="@+id/menu_main_settings_item1"
android:title="item1">
</item>
<item android:id="@+id/menu_main_settings_item2"
android:title="item2">
</item>
<item android:id="@+id/menu_main_settings_item3"
android:title="item3">
</item>
</menu>
</item>
</menu>
『<Project名>→app→src→main→res→values→colors.xml』
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryDark">#303F9F</color>
<color name="colorAccent">#FF4081</color>
<color name="holo_blue_light">#33b5e5</color>
<color name="Background_Cornflowerblue">#6495ED</color>
<color name="Background_MediumslateblueLike">#9b7fff</color>
<color name="ButtonBackground">#d7d7d7</color>
<color name="ButtonShadow">#c6c6c6</color>
<color name="GrayOutText001">#909090</color>
<color name="GrayOutText002">#888888</color>
<color name="GrayOutText003">#777777</color>
<color name="SettingMenuBackground">#eeeeee</color>
<color name="black">#000000</color>
<color name="gray">#808080</color>
<color name="silver">#c0c0c0</color>
<color name="white">#ffffff</color>
<color name="maroon">#800000</color>
<color name="red">#ff0000</color>
<color name="purple">#800080</color>
<color name="fuchsia">#ff00ff</color>
<color name="magenta">#ff00ff</color>
<color name="green">#008000</color>
<color name="lime">#00ff00</color>
<color name="olive">#808000</color>
<color name="yellow">#ffff00</color>
<color name="navy">#000080</color>
<color name="blue">#0000ff</color>
<color name="teal">#008080</color>
<color name="aqua">#00ffff</color>
<color name="cyan">#00ffff</color>
<color name="pink">#ffc0cb</color>
<color name="orange">#ffa500</color>
<color name="greenyellow">#adff2f</color>
<color name="yellowgreen">#9acd32</color>
</resources>
『<Project名>→app→src→main→res→values→styles.xml』
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
</resources>
『<Project名>→app→main→AndroidManifest.xml』
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.sdcard">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme" >
<activity android:name=".MainActivity"
android:launchMode="singleInstance" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
|
|
|