ラベル Android の投稿を表示しています。 すべての投稿を表示
ラベル Android の投稿を表示しています。 すべての投稿を表示

2018年11月9日金曜日

Activityのスタックを確認したいとき

目的

特定のアプリで生きているActivityの一覧を確認する。

前提

・PCでadbコマンドが実行できる状態
・確認したいアプリが起動している端末のUSBデバッグが有効な状態
・PCに端末が接続されている

次のコマンドを実行する

adb shell dumpsys activity activities | grep "Run" | grep "(パッケージ名)"


2018年7月4日水曜日

AndroidでC / C++ファイルがビルドできなくなったときに確認すること

環境

Android Studio 3.1.3
Mac OS X 10.13.1

確認すること

 1.環境が整っているか

Tools > Android > SDK Manager の 
[LLDB]、[CMake]、[NDK]がインストールされているかなど、

https://developer.android.com/studio/projects/add-native-code?hl=ja

このページの設定が一通りできているか確認する

2.".externalNativeBuild"フォルダを削除

<project-root>/<module-root>/.externalNativeBuild フォルダを削除し、再度ビルドする

3.プロジェクトをクリーンする

Build > Clean Project
を実行する

4.キャッシュをクリアする

File > Invalidate Caches / Restart
を実行し、Android Studioを再起動する

5.NDKのバージョンを変更してみる

Android StudioのNDKをダウングレードする方法

環境

Android Studio 3.1.3
Mac OS X 10.13.1

やりたいこと

Android Studioで利用しているNDKのバージョンをダウングレード
今回はr17bから16bにダウングレード

NDKのバージョンを確認

Android Studio > Preferences... > Appearance & Behavior > System Settings > Android SDK > SDK Tools

ダウングレードの手順

1.ダウングレードしたいバージョンのNDKをダウンロード

ここ( https://developer.android.com/ndk/downloads/older_releases )から欲しいバージョンをダウンロードする。

2.Android-sdkのndkを1.でダウンロードしたものと置き換える

SDKの場所をPreferencesで確認

Android Studio > Preferences... > Appearance & Behavior > System Settings > Android SDKのAndroid SDK Location

ndkのフォルダを置き換え

Android SDK Locationの「ndk-bundle」を削除→1.でダウンロードしたフォルダを「ndk-bundle」にリネームし、Android SDK Locationに配置

3.NDKのバージョンを確認

17.1.4828580 から 16.1.4479499 にバージョンが変化していることを確認

2018年7月3日火曜日

BottomNavigationViewのテキストを常に表示する

確認バージョン

supportLibrary: '28.0.0-alpha3'

やりたいこと

BottomNavigationViewの各項目すべてのテキストを常に表示し、Shiftingさせない

対応方法

layoutのxmlファイルでBottomNavigationView にapp:labelVisibilityMode="labeled"を設定する

<android.support.design.widget.BottomNavigationView
    android:id="@+id/bottom_navigation_view"
    android:layout_width="match_parent"
    android:layout_height="56dp"
    android:layout_gravity="bottom"
    android:background="@color/white"
    app:elevation="8dp"
    app:labelVisibilityMode="labeled"
    app:itemIconTint="@color/slector_bottom_navigation"
    app:itemTextColor="@color/slector_bottom_navigation"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:menu="@menu/bottom_navigation" />


heightの56dpは、https://material.io/design/components/bottom-navigation.html#specs を参考

✕今までの対応方法(P以降の端末では正常動作しない)

val menuView = view.getChildAt(0) as BottomNavigationMenuView
try {

    val shiftingMode = menuView::class.java.getDeclaredField("mShiftingMode")
    shiftingMode.isAccessible = true
    shiftingMode.setBoolean(menuView, false)
    shiftingMode.isAccessible = false

    for (i in 0 until menuView.childCount) {
        val bottomNavigationItemView = menuView.getChildAt(i) as BottomNavigationItemView
        bottomNavigationItemView.setShiftingMode(false)
        bottomNavigationItemView.setChecked(false)
    }
} catch (e: NoSuchFieldException) {
    Log.d(TAG, "ERROR", e)
} catch (e: IllegalAccessException) {
    Log.d(TAG, "ERROR", e)
}

↑これだと、non-SDKのリストのリフレクションを利用しているため、
バージョンがAndroid P以降の端末でExceptionが発生するので、実装不可

Androidのnon-SDKのリスト確認場所

https://android.googlesource.com/platform/prebuilts/runtime/+/master/appcompat/



2017年7月20日木曜日

[Kotlin]スコープ関数のlet, with, run, apply, also の違い

を3日くらいにらめっこして、Kotlinのスコープ関数の違いについてざっくりとまとめてみました。

確認環境
Android Studio 3.0 Canary 7
Kotlin 1.1.3-2
macOS Sierra 10.12.15


returnがレシーバ returnが任意
レシーバの
拡張関数
apply with
run
任意の型の
拡張関数
also let

レシーバの拡張関数のとき
  • thisがラムダ式の内と外で参照先が違う
  • レシーバのprotected, privateの関数は呼び出せない
  • this@MainActivityのような記述で、外のthisも呼び出し可能

任意の型の拡張関数のとき
  • thisがラムダ式の内と外で参照先が一緒
  • レシーバをitで呼び出せる
  • itの代わりに任意の変数名の定義も可能(可読性UPに繋がる)

returnがレシーバのとき
  • 戻り値がレシーバ自身なので、用途に合っていれば1行コードが減る

2017年1月11日水曜日

WebViewでハマってたところをCrosswalkで解決

ifreamを含むページがWebViewでうまく動作してくれない(ブラウザアプリで表示とWebViewで表示とで、挙動が一致しない)問題に直面し、ハマっておりました。

WebViewをIntelが開発しているオープンソースライブラリCrossWalk のXWalkViewに置き換えたところ、ifream内も正常に動作してくれました!

置き換え時にやったこと


1.app/build.gradle

repositories {
    maven {
        url 'https://download.01.org/crosswalk/releases/crosswalk/android/maven2' 
    }
}

android {
    // ...
}
dependencies {
    // ...
compile "org.xwalk:xwalk_core_library:17.46.448.10"
 // ...
}

2.Java

  • webview.getSettings().setJavaScriptEnabled(true)の設定は削除(該当メソッドは無いけど、javascriptは有効になってるっぽい)
  • webView.loadUrl -> loadに変更
  • @JavascriptInterface -> @org.xwalk.core.JavascriptInterfaceに変更
  • webview.setWebViewClient -> setResourceClientに変更
    • shouldOverrideUrlLoading 継承(遷移しようとするURLの取得)。戻り値にtrue
    • WebViewClient#onPageStartedのかわりにXWalkResourceClient#onLoadStartedを継承
    • WebViewClient#onPageFinishedのかわりにXWalkResourceClient#onPageFinishedを継承

3.xml

  • <WebView を <org.xwalk.core.XWalkViewに変更


License

3-clause BSD license(三条項BSDライセンス) (New BSD License(修正BSDライセンス ) とも呼ばれている)
ライセンスと著作権の表示が必須で、商用利用、修正、配布、派生物に別の条件を課すことが可能です。

参考


2015年11月8日日曜日

KotlinでFragmentTransaction用の拡張関数

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        fragmentTransaction { ft -> ft.add(R.id.fragment_container, MainFragment()) }
    }

    fun AppCompatActivity.fragmentTransaction(transaction: (ft: FragmentTransaction) -> Unit) {
        val ft = supportFragmentManager.beginTransaction()
        transaction(ft)
        ft.commit()
    }
}

2015年10月17日土曜日

NumberpickerやDatePicker,TimePickerでキーボードの非表示設定

NumberpickerやDatePicker,TimePickerでソフトウェアキーボードがでないように設定するには、

ViewGroup#setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
を設定して、ピッカーにフォーカスがいかないように設定することによって、ピッカーをタップしてもキーボードが表示されなくなる。


http://developer.android.com/reference/android/view/ViewGroup.html#setDescendantFocusability(int)
http://developer.android.com/reference/android/view/ViewGroup.html#FOCUS_BLOCK_DESCENDANTS

ActionBarの戻る矢印の色を変更

// 矢印の色変更
final Drawable upArrow = getResources().getDrawable(R.drawable.abc_ic_ab_back_mtrl_am_alpha);
upArrow.setColorFilter(getResources().getColor(R.color.drawer_arrows), PorterDuff.Mode.SRC_ATOP);
getSupportActionBar().setHomeAsUpIndicator(upArrow);

lintチェックのコマンド

./gradlew app:lint

フォーカスが外れたとき、ソフトキーボードを非表示にするEditText

public class AutoHideKeyboardEditText extends EditText {

    protected boolean mHideKeyboardEnable = true;

    public AutoHideKeyboardEditText(Context context) {
        super(context);
    }

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

    public void setHideKeyboardEnable(final boolean enabled) {
        mHideKeyboardEnable = enabled;
    }

    @Override
    protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
        super.onFocusChanged(focused, direction, previouslyFocusedRect);
        if (mHideKeyboardEnable && !focused) {
            // ソフトキーボードを非表示にする
            final InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
            imm.hideSoftInputFromWindow(getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
        }
    }
}

ブラウザ起動時に、ブラウザアプリ選択を表示しない起動処理

public static void openBrowser(final Context context, final String url) {
    try {
        // 標準ブラウザ起動
        final Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
        intent.setClassName("com.android.browser", "com.android.browser.BrowserActivity");
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent);
    } catch (ActivityNotFoundException e) {
        try {
            // chrome起動
            final Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
            intent.setClassName("com.android.chrome", "com.google.android.apps.chrome.Main");
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(intent);
        } catch (ActivityNotFoundException e2) {
            // 暗黙的intentでブラウザ起動
            final Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(intent);
        }
    }
}

アプリがインストール済みか調べるとき

public boolean isInstalled(final Context context) {
    final Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("scheme:"));
    final List resolveInfos = context.getApplicationContext()
            .getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
    return (resolveInfos != null && !resolveInfos.isEmpty());
}

2015年6月30日火曜日

Ubuntu15.04にAndroidStudio1.2.2を入れてみた

ほぼまっさらなUbuntu15.04にAndroidStudio1.2.2を入れました。

去年の様子
Ubuntu14.04にAndroid Studio入れてみた
→ Android StudioをUbuntuのランチャーから起動できるように設定する

AndroidStudioの環境設備

AndroidStudioのダウンロード

https://developer.android.com/sdk/index.html
の「DOWNLOAD ANDROID STUDIO FOR LINUX」からダウンロード
圧縮ファイルを好きな場所に解凍する。
今回は/home/ysakaguchi/Androidに解凍

SDK Toolsをダウンロード


https://developer.android.com/sdk/index.html#Other
の「SDK Tools Only」から「android-sdk_r24.3.3-linux.tgz」ダウンロード
好きな場所に解凍する
今回は/home/ysakaguchi/Androidに解凍

JDKをインストール

sudo apt-get install openjdk-7-jdk

インストールできているか確認
java -version

必要なlibファイルをインストール

sudo apt-get install libc6-i386 lib32stdc++6 lib32gcc1 lib32ncurses5 zlib1g lib32z1


環境設備が終わったら、AndroidStudioにSDKのパスを設定する

AndroidStudioを起動


セットアップの案内のウィンドウが開くので、閉じます。


もう二度と開かなくていい場合は、「Do not re-run the setup wizard」を選択し「OK」


SDKのパス設定

SDKのパス設定閉じると、またウィンドウが開くので、そこで
「Configure」>「Project Defaults」>「Project Structure」で「Android SDK location」を設定
ダウンロードしたSDK Toolsの解凍先を設定する。
今回は
/home/ysakaguchi/Android/android-sdk-linux
に設定



 Configureに戻って「SDK Manager」を開くことができれば、OK


他の設定

gitをインストール

sudo apt-get install git

ランチャーから起動設定

適当なテキストエディタでテキストファイルを新規作成し、次の記述をコピペ

[Desktop Entry]
Encoding=UTF-8
Version=1.0
Type=Application
Name=Android Studio
Icon=/home/ysakaguchi/Android/android-studio/bin/studio.ico
Path=/home/ysakaguchi/Android/android-studio/bin
Exec=/home/ysakaguchi/Android/android-studio/bin/studio.sh

「Android Studio.desktop」の名前で保存

「Android Studio.desktop」ファイルを右クリック > プロパティ > アクセス権 > 実行:の「プログラムとして実行可能」にチェックをつける

これで、Android Studio.desktopファイルをダブルクリックするとAndroid Studioが起動する
起動すると、ランチャーにアイコンが表示されるので、そこから「launcherに登録」ができる

起動しないときは/home/ysakaguchi/Android/android-studio/bin/studio.shファイルを右クリック > プロパティ > アクセス権 > 実行:の「プログラムとして実行可能」にチェックが入っているか確認する。





2015年5月13日水曜日

NotificationのPendingIntentで注意すること

  • PendingIntent#getActivity
  • PendingIntent#getService
  • PendingIntent#getBroadcast
の第四引数は「PendingIntent.FLAG_CANCEL_CURRENT」を指定する。

理由

PendingIntent.FLAG_UPDATE_CURRENT を指定していると、一部機種でうまく動作しないことがあるため

不具合の再現手順

  1. PendingIntent.FLAG_UPDATE_CURRENTを指定したNotificationを行う
  2. アプリをアンインストール
  3. 同一アプリを再インストール
  4. 1.と同様のNotificationを行う
上記手順を行うと、ステータスバーにある通知をタップしてもgetActivityで指定しているActivityが起動されないなどの不具合が一部端末で発生する
(現状、Xperia Z2 SO-03F確認)

原因の予想

FLAG_UPDATE_CURRENT は、「存在していればそれを使う。新しい設定で置き換えない。」動作を行うフラグのため、
アンインストール前の同一PendingIntentのNotificationが残っており、アンインストール前の情報のアプリを起動しようとしているためだと思われます。



PendingIntent.FLAG_CANCEL_CURRENTを指定すると、「現在設定されているものがあれば、それをキャンセルして新しい設定を行う。」ので、正常に動作されました。

2015年3月17日火曜日

build.gradleにFacebookSDKを追加

ここでセントラルリポジトリ内のFacebookSDKの最新バージョンをチェックする。


build.gradleに下記を追加
repositories {
…
    mavenCentral()
…
}

dependencies {
…
    compile 'com.facebook.android:facebook-android-sdk:3.23.1'
…
}

2015年3月16日月曜日

not available for offline mode

プロジェクトのgradleのdependenciesに新たにライブラリを追加したとき、

Failed to resolve:~
not available for offline mode
と警告が出たら


Android Studio > Preference > GradleのOffline workのチェックを外して、オフラインモードを解除して、再度ビルドしてみる

2015年3月8日日曜日

EditTextで絵文字を含む文字列の文字数制限処理

絵文字を含む文字列の文字数制限で少しハマりました。
最終的に以下のコードで対応しました。
final int MAX_TEXT_LENGTH = 10;
final EditText editText = (EditText) findViewById(R.id.edit_text);
editText.addTextChangedListener(new TextWatcher() {
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
    }

    @Override
    public void afterTextChanged(Editable s) {
        if (unfixInput(s)) {
            return;
        }
        final String str = s.toString();

        final String adjustedText = adjustText(str);
        if (!str.equals(adjustedText)) {
            editText.setText(adjustedText);
            editText.setSelection(editText.getText().length());
            Toast.makeText(getApplicationContext(), String.format("最大%d文字です", MAX_TEXT_LENGTH), Toast.LENGTH_SHORT).show();
            return;
        }
        // TODO 内容保存処理
    }

    /**
     * 入力確定前の文字があるときtrue
     */
    private boolean unfixInput(final Editable s) {
        Object[] spanned = s.getSpans(0, s.length(), Object.class);
        if (spanned != null) {
            for (Object obj : spanned) {
                if ((s.getSpanFlags(obj) & Spanned.SPAN_COMPOSING) == Spanned.SPAN_COMPOSING) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 文字列の調整
     */
    private String adjustText(final String str) {
        if (MAX_TEXT_LENGTH < str.codePointCount(0, str.length())) { // 文字数は、コードポイントで比較
            return adjustText(str.substring(0, (str.length() - 1)));
        }
        return str;
    }
});

ハマった原因

xmlのEditTextに
android:maxLength="10"
と設定しても、 文字数のカウントがサロゲートの文字が配慮されておらず、絵文字など、文字コードがサロゲートの場合、1文字で2文字と認識されてしまいます。
そのため、最大10文字と設定していても、絵文字を含む文字列だと5〜9文字までしか入力できないEditTextになってしまいます。

対処方法

  • EditTextのmaxLengthは使用しない
  • 文字数のカウントは、String#codePointCountメソッドを使用する

コードポイントとは

コードポイントとは、Unicodeで1文字分のコードを示す言い方。Javaではコードポイントはint型で表す。(引用元:http://www.ne.jp/asahi/hishidama/home/tech/java/string.html)

他、参考



2015年1月30日金曜日

「パッケージファイルに正しく署名されていません」にハマった

署名したapkをPlayストアにアップしたら、一部の端末で
「パッケージファイルに正しく署名されていません」が表示され、インストール不可の状態になった。


開発環境

Android Studio : 1.0.1
Ubuntu : 14.04
Java : OpenJDK1.7.0_65

原因

jarsignerの署名方式のデフォルト値がJDK6までとJDK7以降で変更されているようです。
そのため、コマンド実行でJDK7を使用して署名を行ったため「パッケージファイルに正しく署名されていません」と表示される端末が発生しました。

参考:
JDK7でAndroidアプリをリリースビルドする方法
Androidアプリをリリースしたら「パッケージファイルに正しく署名されていません」と表示されて焦ったでござる

解決方法

build.gradleに署名用の記述追加(OpenJDK1.7.0_65のままで大丈夫でした)
参考:AndroidStudio で APK の署名の設定を gradle.properties に記述する

gradle.propertiesに署名関連の設定を記述することで、
gitignoreでgradle.propertiesをgit管理の対象外にすると、署名ファイルのパスワードなどをアップせずに済むので、とても良いです。

gradle.propertiesに記述する
storeFile=/path/to/your.keystore

は、キーストアファイルのある場所が、/home/ysakaguchi/android/release/android.keystoreなら
storeFile=/android/release/android.keystore
となります。

確認方法

deploygateに修正したapkをアップして、JDK7のデフォルト署名方式だとうまくインストールできなかった端末で、再度インストールを試みたところうまくいくことも、先に確認できました。
「パッケージファイルに正しく署名されていません」が発生する端末は、どれなのかまでは絞れてないですが、SHARP端末はなるっぽい?かもです。
手元にIS05があったので、本件の現象が再現できました。
Xperiaは署名方式が違ってもダウンロードできていました。


ちなみに今回の件が分かったアプリはこちらになります↓