Sources for 'Android API xx Platform' not found.
概要
Build.javaを開くとSources for 'Android API 22(1) Platform' not found.
というエラーが出てきました.
インストールしても直らない🤔
(インストールされているかは,Tools > Android > SDK Manager > Show Pachage Details > Sources for Android xxがInstalledになっているかで確認できます)
Refreshを押しても反応しない🤔
(バグらしいです.泣)
という時に以下の方法で解決できたので紹介します.実行環境はAndroid2.1系と2.3系です.
解決方法
①Tools > Android > SDK Managerを開く
②Android SDK LocationのEditを押す
③何もいじらず,NextをポチポチしてFinish
これでRefreshされ解決されました.
参考
Android Spinner#onItemSelectedが起動時にも実行されることへの対策
Spinner#onItemSelected
初回起動時もSelectされたとして反応してしまいます.
初回は処理を避けたい時の対応方法を紹介します.
実装
よくある方法にSpinnerがフォーカス可能かをフラグとして使うものがあります.
falseが初回起動,trueがそれ以降です.
バックグラウンドから復帰した時は初回と判定されます.
フォーカス可能かはSpinner#setFoucusable
で設定できて,値はSpinner#isFocusable
で取得できます.
もちろんフォーカスの代わりにメンバー変数でFlagを持っといてもOKです. メンバー変数バージョンはコメントアウトに記載しました.
MainActivity.java
public class MainActivity extends AppCompatActivity { private Spinner mSpinner; // private boolean mIsFirstBoot = true; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mSpinner = (Spinner) findViewById(R.id.spinner); mSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { // 初回起動時の動作 if (mSpinner.isFocusable() == false) { // if (mIsFirstBoot) { mSpinner.setFocusable(true); // mIsFirstBoot = false; Toast.makeText(getApplicationContext(), "初回起動", Toast.LENGTH_SHORT).show(); return; } // 初回以降の動作 Toast.makeText(getApplicationContext(), "初回以降", Toast.LENGTH_SHORT).show(); } @Override public void onNothingSelected(AdapterView<?> parent) { } }); // 初回起動時の対応 mSpinner.setFocusable(false); } }
activity_main.xml
(略) <Spinner android:id="@+id/spinner" android:entries="@array/list" android:layout_width="wrap_content" android:layout_height="wrap_content"></Spinner> (略)
strings.xml
<resources> <string name="app_name">TestApp001</string> <string-array name="list"> <item>hoge</item> <item>fuga</item> <item>piyo</item> </string-array> </resources>
参考
Android Web to Appする(アプリ編)
App Indexing
AndroidにはApp Indexingという仕組みがあります.
AppIndexingとは、ウェブページURLやキーワードとアプリの特定画面へのディープリンクを紐付け、Google検索結果から直接アプリの特定画面を起動させるための仕組みです。 by Qiita
ウェブもアプリも持っているサービスなんかは,この仕組みを使うと簡単にWeb to Appできます.
※ウェブからもアプリからも実装が必要なんですが今回はアプリ側の実装を紹介します.
設定はAndroidManifest.xmlだけで可能です.
<intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="https" android:host="m.yahoo.co.jp" android:path="/" /> <data android:scheme="http" android:host="m.yahoo.co.jp" android:path="/" /> </intent-filter>
actionタグにはVIEW
,categoryタグにはBROUSABLE
,DEFAULT
を書きます.
DEFAULT
は任意です.指定しないとGoogle検索結果以外からディープリンクできなくなります.
dataタグにはschemeなどを指定します.何が指定できるかは公式ドキュメントをご覧ください→<data> | Android Developers
今回はこんな感じ.
scheme https://m.yahoo.co.jp/
host https://m.yahoo.co.jp/
path https://m.yahoo.co.jp/
起動できるかはasb
コマンドでテストできます.
$ adb shell am start -a android.intent.action.VIEW -d "https://m.yahoo.co.jp/" {package name}
Android Homeキーのタップを検知する
dispatchKeyEvent
でいけるかなと思っていましが,これはハードキー時代の栄光のようです.
Homeキーのタップを検知する方法には
1). onUserLeaveHint
2). BroadcastReceiver
の2つあります. 1). はIntentで他アプリに遷移するときも呼ばれるので注意が必要です.
1). onUserLeaveHint
@Override protected void onUserLeaveHint() { Toast.makeText(getApplicationContext(), "ホームボタンが押されました", Toast.LENGTH_LONG).show(); }
2). BroadcastReciever
public class MainActivity extends AppCompatActivity { private HomeKeyReceiver mHomeKeyReceiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Homeキーを押された時の Reciever の登録 mHomeKeyReceiver = new HomeKeyReceiver(); IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); registerReceiver(mHomeKeyReceiver, filter); } private class HomeButtonReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent){ Toast.makeText(getApplicationContext(), "ホームボタンが押されました", Toast.LENGTH_LONG).show(); finish(); } } @Override public void onPause(){ super.onPause(); unregisterReceiver(mHomeKeyReceiver); } }
this version of Android Studio is incompatible with the Gradle Plugin used. Try disabling Instant Run
エラー内容
git clone
してきたアプリをrunしようとしたら,こんなメッセージが出てヒーってなったんですが,あっさり解決できたんで方法を記したいと思います.
this version of Android Studio is incompatible with the Gradle Plugin used. Try disabling Instant Run (Android Studioのこのバージョンは使われているGradle Pluginと互換性がないよ.Instant Runを無効にしてみてね)
解決方法
Android Studioのバージョンによって設定方法が微妙に異なると思いますが,私の使っているAndroid Studio2.1系のやり方です.
①Instant Runの設定変更
Android Studio>Preferences>Build, Execution, Deployment>Instant Runで
- Enable Instant Run to hot swap code/resource change on deploy (default enabled)←Instant Runを有効にするか
- Show Instant Run status notifications←Instant Rundに関する通知を表示するか(こちらはチェックつけてもつけなくても変わらない気がする)
のチェックを外す.
②Clean Project
Build>Clean Projectをする.
③いつも通りrun!
参考
App ShortcutsのStatic Shortcutsを実装してみる
App Shortcutsとは
Android 7.1(SDK 25)で追加されたショートカットを作成する機能です.
アプリを長押しすると,ショートカットの機能が出てきます.
吹き出しをタップすることで指定したintentを起動できます.
図1: ショートカット(左上)
ショートカットは先ほどの吹き出しを長押しすることで,ホーム画面にピン留めできます.
図2: ピン留めされたショートカット(左上)
App Shortcutsには二種類あります.
- Static Shortcuts:xmlで定義する静的なショートカット
- Dynamic Shortcuts:Shortcut Managerを利用する動的なショートカット
です.
実装
今回はStatic Shortcutsを作ります.
①AndroidManifest.xmlを定義する
ルートActivityにmeta-dataを追加します.@xml/shortcut
はショートカットを設定したxmlです.コードは②に載せています.
(略) <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"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <meta-data android:name="android.app.shortcuts" android:resource="@xml/shortcuts" /> </activity> <activity android:name=".ComposeActivity" /> </application> (略)
②shortcuts.xmlを定義する
<?xml version="1.0" encoding="utf-8"?> <shortcuts xmlns:android="http://schemas.android.com/apk/res/android"> <shortcut android:shortcutId="compose" android:enabled="true" <!-- falseにするとこのショートカットは無効化される --> android:icon="@drawable/icon" android:shortcutShortLabel="@string/compose_shortcut_short_label1" <!-- アプリ長押し時に出るラベル名 --> android:shortcutLongLabel="@string/compose_shortcut_long_label1" <!-- ピン留めしたショートカットのラベル名 --> android:shortcutDisabledMessage="@string/compose_disabled_message1"> <!-- 無効化されたショートカットをタップした時に出る文言 --> <intent android:action="android.intent.action.VIEW" android:targetPackage="com.example.a01.appshortcut" android:targetClass="com.example.a01.appshortcut.ComposeActivity" /> <categories android:name="android.shortcut.conversation" /> </shortcut> </shortcuts>
参考
EventBusを使って簡単にCallbackを実現する
EventBusとは
あるClassでのイベントを検知して,別のClassで何かしたい時ありませんか?
Androidには簡単にそんなCallbackを実現する仕組みがあります.それがEventBusです.
例えば,ショッピングアプリの商品ページでお気に入りボタンが押された時,未ログインならログインページに飛ばし,ログイン完了後,再び商品ページに戻してお気に入り登録処理をしたい,なんて時に使えます(^^)
今回はgreenrobotのEventBusを使いますが,EventBusの提供元は一つではないです.
こちらにはsquere社のEventBusも紹介されています. qiita.com
実装
以下のgithubに載っていますが,EventBusは3stepで実現できちゃいます. github.com
今回は「ボタンがクリックされるとMessageEventというイベントが投げられ,MainActivityにToastを表示する」アプリを実装します.
イベントを投げるActivityも受けるActivityも同じなんで有難味がないかもしれませんが,簡略化のためそうします.
①イベント定義 (MessageEvent.java)
まず,ボタンがクリックされたことを通知するイベントClassを作ります.
MessageEvent.java
public class MessageEvent { }
②イベントを監視する準備 (MainActivity.java)
次にイベントの監視を設定します.
通知を受け取りたいクラスのonStartにEventBus.getDefault().register(this);
と書き
立つ鳥跡を濁さず,onStopではEventBus.getDefault().unregister(this);
をして登録解除します.
③イベントを投げる (MainActivity.java)
最後に,イベントを発火したいタイミングでEventBus#getDefault#postします.
引数は発火したいイベントクラスです.
EventBus.getDefault().post(new MessageEvent());
MainActivity.java
import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.Toast; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button button = (Button) findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { EventBus.getDefault().post(new MessageEvent()); } }); } @Subscribe(threadMode = ThreadMode.MAIN) public void onMessageEvent(MessageEvent event) { Toast.makeText(this, "イベント発火", Toast.LENGTH_SHORT).show(); } @Override public void onStart() { super.onStart(); EventBus.getDefault().register(this); } @Override public void onStop() { super.onStop(); EventBus.getDefault().unregister(this); } }
build.gradleはこちら
compile 'org.greenrobot:eventbus:3.0.0'
簡単で便利なのでよかったら使ってみてくださーいノシ