2016年10月1日土曜日

Android端末がWindowsで認識しない

Android端末がWindowsで認識しない

今まで問題なく認識できていたAndroid端末が、2016年10月1日に、Windows10で認識できなくなりました。
私の事例の場合、Windows10に接続するUSB機器を、キーボード、マウス及びAndroid端末の3個だけにすれば、問題なくAndroid端末を認識できるようになりました。
第四番目に接続させていたUSB機器との相性が悪かったのかと思います。

2016年7月11日月曜日

「データがありません」ANRに関する報告の受け取り

「データがありません」ANRに関する報告の受け取り

ANRの報告に「データがありません」という表示がされる場合があります。
この場合、半日程度経ってから、ドラム缶アイコンから「クラッシュとANR」を選択し、ANRデータをCSVファイルで開発機にダウンロードして、見てください。
そうすると、ある程度情報が記載させています。


2016年3月9日水曜日

BroadcastReceiverでIntent.ACTION_PACKAGE_REPLACEDを受け取る

BroadcastReceiverでIntent.ACTION_PACKAGE_REPLACEDを受け取る

アプリの改版を行った場合、アプリは、BroadcastReceiverでandroid.intent.action.PACKAGE_REPLACEDを受け取ります。
このPACKAGE_REPLACEDに基づき実行されるコードは、旧版でしょうか、それとも新版でしょうか。

解答は、新版です。

何の根拠も無く、間違った方で、自分勝手に思い込みをしてしまわないようにしましょう。

2016年2月29日月曜日

PreferenceFragmentを使って複雑なViewGroupを表示・操作したい場合

PreferenceFragmentを使って複雑なViewGroupを表示・操作したい場合

表示する画面のxml:preference_version.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    >
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:autoLink="web"
        android:text="@string/test"
        >
    </TextView>
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        >
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:layout_alignParentLeft="true"
            android:layout_alignParentStart="true"
            android:paddingTop="20dp"
            android:text="@string/app_name"
            >
        </TextView>
        <TextView
            android:id="@+id/TextView_Preference_Version"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_alignParentEnd="true"
            android:layout_centerVertical="true"
            android:paddingTop="20dp"
            >
        </TextView>
    </RelativeLayout>
</LinearLayout>

\res\xml\preferences.xml
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android"
    >
    <PackageName.VersionPreference
        android:key="PreferenceScreen_Version"
        android:layout="@layout/preference_version"ここがポイント
widgetLayoutを使うと適切に表示されない。
        >
    </PackageName.VersionPreference>
</PreferenceScreen>

PackageName.VersionPreference.java
public class VersionPreference extends Preference{
    private Context con;
    public VersionPreference(Context context){
        super(context);
        con = context;
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public VersionPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        con = context;
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public VersionPreference(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        con = context;
    }

    public VersionPreference(Context context, AttributeSet attrs) {
        super(context, attrs);
        con = context;
    }

    @Override
    protected void onBindView(View view){
        super.onBindView(view);
        LinearLayout llParent = (LinearLayout) view;
        TextView tv = (TextView) llParent.findViewById(R.id.TextView_Preference_Version);
        PackageInfo pi;
        try{
            pi = con.getPackageManager().getPackageInfo(
                    con.getPackageName(),
                    PackageManager.GET_ACTIVITIES
            );
            Resources r = con.getResources();
            String s = r.getString(R.string.Version) + pi.versionName;
            tv.setText(s);
        }
        catch(PackageManager.NameNotFoundException e){
        }
    }
}

ListPreferenceを使って、longのデータを保存・読込を行う

ListPreferenceを使って、longのデータを保存・読込を行う

ListPreferenceをそのまま使うと、保存・読込のデータはStringになる。
これは不便だ。そこで、longによりデータの保存・読込を行う。

public class myLP extends ListPreference{
    public myLP(Context context){
        super(context);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public myLP(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public myLP(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public myLP(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onSetInitialValue(boolean restoreValue, Object defaultValue){
        if(restoreValue){//long型データをファイルから読む。
            long lValue;
            String s;
            lValue = //PreferenceManager.getDefaultSharedPreferences()を使ってデータを読む。
            s = String.valueOf(lValue);
            setValue(s);
        }
        else{//ファイルへ保存する。
            //このファイルへ保存する部分は、別途本体において、自分でプログラムする。
        }
    }
}

class SettingsFragment extends PreferenceFragmentにて
    @Override
    public boolean onPreferenceChange(Preference preference, Object newValue){
        String sValue = (String)newValue;
        //Long.parseLong(sValue)を
        //PreferenceManager.getDefaultSharedPreferences()を使って保存する
        return true;
    }

(参考)

2016年2月6日土曜日

PreferenceFragmentの評価


PreferenceFragmentの評価
Preference情報を基調としているPreferenceFragmentの評価はどうなのだろうか。
CheckBoxPreference等ごく限られた道具しかない。データの出し入れに特化したものだ。画面表示関係には弱い。
例えば、PreferenceScreenにButtonを配置したい場合、どうするのか。

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
        Preference preferenceButton = findPreference("PreferenceScreen_btnClose");
        preferenceButton.setLayoutResource(R.layout.preference_button);
        preferenceButton.setOnPreferenceClickListener(this);
        return super.onCreateView(inflater, container, savedInstanceState);
    }

    @Override
    public boolean onPreferenceClick(Preference preference){
        if(preference==findPreference("PreferenceScreen_btnClose")){
            //ここでButton押し下げ関係処理をする
            return true;
        }
        return false;
    }

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android"
    >
    <Preference
        android:key="PreferenceScreen_btnClose"
        >
    </Preference>
</PreferenceScreen>

R.layout.preference_button
<?xml version="1.0" encoding="utf-8"?>
<Button
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:text="@string/aaaa"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:clickable="false"(必要)
    android:focusable="false"(必要)
    android:drawableStart="@android:drawable/ic_menu_close_clear_cancel"
    >
</Button>

単純にクリックするだけであれば悩まない。
複雑なViewGroupを表示・操作したい場合どうするのか。
Preferenceを拡張して行うということである。職人技ですね。普通のプログラマーが自力だけでこのコードを書けるとは思えない。
「複雑な形状のViewの表示は別途画面を設けてください」というのが、本システム設計者の考え方かもしれない。



SharedPreferences

SharedPreferences

SharedPreferencesを用いてデータを保存する方法は2通りある。

その1.
Context.getSharedPreferences("thisName", Context.MODE_PRIVATE)を使う方法
簡単なサンプルは次のとおりです。
boolean b;
SharedPreferences sp;
sp = con.getSharedPreferences("thisName", Context.MODE_PRIVATE);
b = sp.getBoolean("thisKey", false);

その2.
PreferenceManager.getDefaultSharedPreferences()を使う方法
データを簡単に保存する方法(Preference編)

両者の違いは次のサイトに解説されている。
Difference between getDefaultSharedPreferences and getSharedPreferences
保存する名前(保存先)が異なるとのことである。機能に違いは無い。各々独立したデータとして取り扱うことになる。

仕掛け
Preferencesによるデータはファイルに保存される。
このファイル名は、Context.getSharedPreferences()であれば、その第一引数に指定した文字列になる。
PreferenceManager.getDefaultSharedPreferences()の場合は、context.getPackageName() + "_preferences"という、固定された名前(プログラマーが指定できない名前)になる。

このような名前を持つファイルの中に、任意の個数の、任意の名前のKeyが存在することになる。各々のKeyには、1個の何らかの値がくっついている。
Keyを指定することにより、値を操作することができる。

保存先がファイルであるから、複数設けるとアクセスに時間がかかるかもしれない。ファイルは1個にまとめれば効率的かもしれない。

PreferenceFragmentで使いたい場合
既にContext.getSharedPreferences()を用いてアプリを運用してしまっている場合であって、これをPreferenceFragmentで使用したい場合、取り扱うデータをContext.getSharedPreferences()で保存・読込ができるようにしなければならない。
\res\xml\preferences.xml
<PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android"
    >
    <CheckBoxPreference
        android:key="ここにContext.getSharedPreferences()で使っているKeyを設定する"
        android:title="...."
        android:summary="...."
        >
    </CheckBoxPreference>
</PreferenceScreen>

PreferenceFragment.java
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
        PreferenceManager pm;
        cbQuit = (CheckBoxPreference)findPreference("キー");
        pm = cbQuit.getPreferenceManager();
        pm.setSharedPreferencesName("名前");//取り扱うファイル名を変更する。
        boolean "値" = "変更後のファイルのキーから値を取得する"
        cbQuit.setChecked("値");

チェックボックスが1個だけなら良いが、2個以上の場合、onPreferenceChange()においてしっかりと値を保存しておかねばならない(意味不明)。
        pbQuit.setOnPreferenceChangeListener(this);
        return super.onCreateView(inflater, container, savedInstanceState);
    }

    @Override
    public boolean onPreferenceChange(Preference preference, Object newValue){
        if(preference==cbQuit){
            boolean b = (boolean)newValue;
            (ここで値を保存しておく)
            return true;
        }
        return false;
    }


2016年1月22日金曜日

MountService No primary storage defined yet hacking together a stub

MountService No primary storage defined yet hacking together a stub

Android 6.0のエミュレータで上記のエラーが発生します。
これが原因で他のアプリが動かなくなります。
解決方法は、このエラーが発生するエミュレータを捨てて、Android Virtual Device Managerで新規にエミュレータを作成してください。残念です。