2011-09-21 13 views
8

Android 2.2(またはそれ以降)の電話機でOnAudioFocusChangeListener(Android 2.2 - API 8以降で使用可能)を使用できるAndroid 1.6(API 4)用のアプリケーションを開発する必要があります。後で。Androidでリフレクションを使用してリスナーをインスタンス化する方法

リスナーでリスナーをインスタンス化する方法は誰にでも分かりますか? 私は既に静的メソッドと非静的メソッドをリフレクションで実行することができましたが、リスナーの処理方法はわかりません。

これは反映するリスナーです:

AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 

OnAudioFocusChangeListener audioListener = new OnAudioFocusChangeListener() { 
    @Override 
    public void onAudioFocusChange(int focusChange) { 
    // code to execute 
    } 
}; 

public void getAudioFocus() { 
    audioManager.requestAudioFocus(audioListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN); 
} 

public void releaseAudioFocus() { 
    audioManager.abandonAudioFocus(audioListener); 
} 

これは私が反射によって実行するために管理する方法とコードの例です:

Class BluetoothAdapter = Class.forName("android.bluetooth.BluetoothAdapter"); 
Method methodGetDefaultAdapter = BluetoothAdapter.getMethod("getDefaultAdapter"); // static method from the BluetoothAdapter class returning a BluetoothAdapter object 
Object bluetooth = methodGetDefaultAdapter.invoke(null); 
Method methodGetState = bluetooth.getClass().getMethod("getState"); // non-static method executed from the BluetoothAdapter object (which I called "bluetooth") returning an int 
int bluetoothState = (Integer) methodGetState.invoke(bluetooth); 
+1

こことして、私はラッパーを使用することができ、完全に確認していない良い例のhttp://blogs.oracle.com/poonam/entry/how_to_implement_an_interface – Ronnie

答えて

6

最後に、私はそれをProxyクラスを使って解決しました。ここにコードです!

private AudioManager theAudioManager; 
private Object myOnAudioFocusChangeListener = null; 

private static final int AUDIOMANAGER_AUDIOFOCUS_GAIN = 1; 
private static final int AUDIOMANAGER_AUDIOFOCUS_LOSS = -1; 

theAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 

// instantiating the OnAudioFocusChangeListener by reflection (as it only exists from Android 2.2 onwards) 
// we use a Proxy class for implementing the listener 
public void setOnAudioFocusChangeListener() { 
    Log.i(this, "setOnAudioFocusChangeListener()"); 
    Class<?>[] innerClasses = theAudioManager.getClass().getDeclaredClasses(); 
    for (Class<?> interfaze : innerClasses) { 
     if (interfaze.getSimpleName().equalsIgnoreCase("OnAudioFocusChangeListener")) { 
      Class<?>[] classArray = new Class<?>[1]; 
      classArray[0] = interfaze; 
      myOnAudioFocusChangeListener = Proxy.newProxyInstance(interfaze.getClassLoader(), classArray, new ProxyOnAudioFocusChangeListener()); 
     } 
    } 
} 

// called by onResume 
public void getAudioFocus() { 
    if (myOnAudioFocusChangeListener != null) { 
     Log.i(this, "getAudioFocus()"); 
     try { 
      Method[] methods = theAudioManager.getClass().getDeclaredMethods(); 
      for (Method method : methods) { 
       if (method.getName().equalsIgnoreCase("requestAudioFocus")) { 
        method.invoke(theAudioManager, myOnAudioFocusChangeListener, AudioManager.STREAM_MUSIC, AUDIOMANAGER_AUDIOFOCUS_GAIN); 
        Log.i(this, "requestAudioFocus"); 
       } 
      } 
     } catch (Exception e) { 
      Log.e(this, e.getMessage()); 
     } 
    } 
} 

// called by onPause 
public void releaseAudioFocus() { 
    if (myOnAudioFocusChangeListener != null) { 
     Log.i(this, "releaseAudioFocus()"); 
     try { 
      Method[] methods = theAudioManager.getClass().getDeclaredMethods(); 
      for (Method method : methods) { 
       if (method.getName().equalsIgnoreCase("abandonAudioFocus")) 
        method.invoke(theAudioManager, myOnAudioFocusChangeListener); 
      } 
     } catch (Exception e) { 
      Log.e(this, e.getMessage()); 
     } 
    } 
} 

PROXY OnAudioFocusChangeListenerクラス

private class ProxyOnAudioFocusChangeListener implements InvocationHandler { 

    // implements the method onAudioFocusChange from the OnAudioFocusChangeListener 
    public void onAudioFocusChange(int focusChange) { 
     Log.e(this, "onAudioFocusChange() focusChange = " + focusChange); 
     if (focusChange == AUDIOMANAGER_AUDIOFOCUS_LOSS) { 
      Log.i(this, "AUDIOMANAGER_AUDIOFOCUS_LOSS"); 
      Message msg = mHandler.obtainMessage(ControllerHandler.SET_ON_PAUSE); 
      mHandler.sendMessage(msg); 
     } else if (focusChange == AUDIOMANAGER_AUDIOFOCUS_GAIN) { 
      Log.i(this, "AUDIOMANAGER_AUDIOFOCUS_GAIN"); 
      // no action is taken 
     } 
    } 

    // implements the method invoke from the InvocationHandler interface 
    // it intercepts the calls to the listener methods 
    // in this case it redirects the onAudioFocusChange listener method to the OnAudioFocusChange proxy method 
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 
     Object result = null; 
     try { 
      if (args != null) { 
       if (method.getName().equals("onAudioFocusChange") && args[0] instanceof Integer) { 
        onAudioFocusChange((Integer) args[0]); 
       } 
      } 
     } catch (Exception e) { 
      throw new RuntimeException("unexpected invocation exception: " + e.getMessage()); 
     } 
     return result; 
    } 
} 
1

IMHO反射は、あなたのクラスが読みにくくなります。また、リフレクションは、通常のフィールドまたはクラスアクセスよりかなり遅いです。 http://android-developers.blogspot.com/2009/04/backward-compatibility-for-android.html

、以前のバージョンのAPIのための1つ8+および他のインターフェースおよびそれの2つの実装を作成します。別のここで説明したラッパークラスのアプローチを見るよう

。 API8クラスでは、OnAudioFocusChangeListenerを含むAPI 8クラスを使用できます。 OSのバージョンに基づいてバージョンをインスタンス化します。これはBuild.VERSION.SDK_INTで確認できます。

+0

です'AudioManager'オブジェクトの' requestAudioFocus'と 'abandonAudioFocus'メソッドへの引数として' OnAudioFocusChangeListener'オブジェクトを渡す必要があります。代わりにOnAudioFocusChangeListenerラッパーを渡すと動作しないと思います。 –

+0

これをラッパークラスの内部クラスとして持つことができます。これはうまくいくでしょう。 –

+0

私はまた、リフレクションにミスを与えるでしょう - それはコードのにおいです - 特にそれを解決する良い方法があるとき。ラッパーメソッドを使用する - はるかに良い。 – Martyn

関連する問題