勉強会メモ

とりあえず読書会メモ。

7.4 ノーティフィケーション

  • NotificationManager#notify
    • getSystemService の中身を見といた方が良いな
  • Notification の属性
  • インテントレシーバから起動される
  • インテントって何だ、という声あり
  • ペンディングインテント?
    • ステイタスバーの表示タップで発行される
    • インテントを生成したアプリケーション以外が発行するために使用

ソース確認

getSystemService の中身が気になったので確認。所在は frameworks/base/core/java/android/app/Activity.java なんですが、定義が以下。

    @Override
    public Object getSystemService(String name) {
        if (getBaseContext() == null) {
            throw new IllegalStateException(
                    "System services not available to Activities before onCreate()");
        }

        if (WINDOW_SERVICE.equals(name)) {
            return mWindowManager;
        } else if (SEARCH_SERVICE.equals(name)) {
            ensureSearchManager();
            return mSearchManager;
        }
        return super.getSystemService(name);
    }

結局、スーパークラスのソレの戻りになっております。ええとクラス定義が以下。

public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory,
        Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks {

javaスーパークラスが一つなので遡り易いですな。frameworks//base/core/java/android/view/ContextThemeWrapper.java が定義元かな。

    @Override public Object getSystemService(String name) {
        if (LAYOUT_INFLATER_SERVICE.equals(name)) {
            if (mInflater == null) {
                mInflater = LayoutInflater.from(mBase).cloneInContext(this);
            }
            return mInflater;
        }
        return mBase.getSystemService(name);
    }

こうなってくると意味分からんな。通常は mBase な getSystemService 手続きを呼んで戻りをそのまま戻しています。mBase は Context なオブジェクトの参照な模様。

    private Context mBase;

Context は frameworks//base/core/java/android/content/Context.java にて定義されている模様。
って定義見たら抽象クラスだったorz

public abstract class Context {

という事は実体は別で定義されているのか。find|grep してみたら以下が出てきました。

frameworks//base/core/java/android/app/Activity.java:    public Object getSystemService(String name) {
frameworks//base/core/java/android/app/ApplicationContext.java:    public Object getSystemService(String name) {
frameworks//base/core/java/android/content/Context.java:    public abstract Object getSystemService(String name);
frameworks//base/core/java/android/content/ContextWrapper.java:    public Object getSystemService(String name) {
frameworks//base/core/java/android/view/ContextThemeWrapper.java:    @Override public Object getSystemService(String name) {
frameworks//base/test-runner/android/test/IsolatedContext.java:    public Object getSystemService(String name) {
frameworks//base/test-runner/android/test/mock/MockContext.java:    public Object getSystemService(String name) {
frameworks//base/tests/FrameworkTest/tests/src/com/android/frameworktest/widget/ListViewTest.java:        public Object getSystemService(String name) {
frameworks//base/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java:    public Object getSystemService(String service) {

例えば ApplicationContext.java だと定義が以下。

    @Override
    public Object getSystemService(String name) {
        if (WINDOW_SERVICE.equals(name)) {
            return WindowManagerImpl.getDefault();
        } else if (LAYOUT_INFLATER_SERVICE.equals(name)) {
            synchronized (mSync) {
                LayoutInflater inflater = mLayoutInflater;
                if (inflater != null) {
                    return inflater;
                }
                mLayoutInflater = inflater =
                    PolicyManager.makeNewLayoutInflater(getOuterContext());
                return inflater;
            }
        } else if (ACTIVITY_SERVICE.equals(name)) {
            return getActivityManager();
        } else if (ALARM_SERVICE.equals(name)) {
            return getAlarmManager();
        } else if (POWER_SERVICE.equals(name)) {
            return getPowerManager();
        } else if (CONNECTIVITY_SERVICE.equals(name)) {
            return getConnectivityManager();
        } else if (WIFI_SERVICE.equals(name)) {
            return getWifiManager();
        } else if (NOTIFICATION_SERVICE.equals(name)) {
            return getNotificationManager();
        } else if (KEYGUARD_SERVICE.equals(name)) {
            return new KeyguardManager();
        } else if (ACCESSIBILITY_SERVICE.equals(name)) {
            return AccessibilityManager.getInstance(this);
        } else if (LOCATION_SERVICE.equals(name)) {
            return getLocationManager();
        } else if (SEARCH_SERVICE.equals(name)) {
            return getSearchManager();
        } else if ( SENSOR_SERVICE.equals(name)) {
            return getSensorManager();
        } else if (BLUETOOTH_SERVICE.equals(name)) {
            return getBluetoothDevice();
        } else if (VIBRATOR_SERVICE.equals(name)) {
            return getVibrator();
        } else if (STATUS_BAR_SERVICE.equals(name)) {
            synchronized (mSync) {
                if (mStatusBarManager == null) {
                    mStatusBarManager = new StatusBarManager(getOuterContext());
                }
                return mStatusBarManager;
            }
        } else if (AUDIO_SERVICE.equals(name)) {
            return getAudioManager();
        } else if (TELEPHONY_SERVICE.equals(name)) {
            return getTelephonyManager();
        } else if (CLIPBOARD_SERVICE.equals(name)) {
            return getClipboardManager();
        } else if (INPUT_METHOD_SERVICE.equals(name)) {
            return InputMethodManager.getInstance(this);
        }

        return null;
    }

例えば

  • WIFI_SERVICE だったら getWifiManager
  • NOTIFICATION_SERVICE だったら getNotificationManager

たとえば getWifiManager メソドの定義は以下。

    private WifiManager getWifiManager()
    {
        synchronized (sSync) {
            if (sWifiManager == null) {
                IBinder b = ServiceManager.getService(WIFI_SERVICE);
                IWifiManager service = IWifiManager.Stub.asInterface(b);
                sWifiManager = new WifiManager(service, mMainThread.getHandler());
            }
        }
        return sWifiManager;
    }

詳細は別途とゆー事で。

しかし

Notification ではなくて、getSystemService 読んでるあたりが微妙だったりして。