【四】注入框架RoboGuice使用:(Your First System Service Injection)

上一篇我们简单的介绍了一下RoboGuice的使用(【三】注入框架RoboGuice使用:(Your
First Resource Injection)
),今天我们来看下系统服务的使用注解的方法:

为了在Activity中系统服务使用注解,必须实现以下两个步骤:

①:创建继承RoboActivity的Activity

②:使用 @Inject来进行注解系统服务

下面我们来实现一个例子,和上一篇文章例子差不多,我们需要进行实现系统服务,我们同样创建一个继承RoboActivity的Activity,然后使用@Inject进行注解服务,其他的操作就放心交给Roboguice帮你做吧。

class MyActivity extends RoboActivity {
    @Inject Vibrator vibrator;
    @Inject NotificationManager notificationManager;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // we can use the instances directly!
        vibrator.vibrate(1000L); // RoboGuice took care of the getSystemService(VIBRATOR_SERVICE)
        notificationManager.cancelAll();

        // rest of your code

从上面可以看出来,RoboGuice知道怎么样根据系统服务来获取该引用对象,如果你想知道RoboGuice内部是怎么样进行绑定服务的可以查看一下DefaultRoboModule.java,下面就是该源代码

package roboguice.config;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import roboguice.activity.RoboActivity;
import roboguice.event.EventManager;
import roboguice.event.ObservesTypeListener;
import roboguice.event.eventListener.factory.EventListenerThreadingDecorator;
import roboguice.fragment.FragmentUtil;
import roboguice.inject.AccountManagerProvider;
import roboguice.inject.AssetManagerProvider;
import roboguice.inject.ContentResolverProvider;
import roboguice.inject.ContextScope;
import roboguice.inject.ContextScopedSystemServiceProvider;
import roboguice.inject.ContextSingleton;
import roboguice.inject.ExtrasListener;
import roboguice.inject.HandlerProvider;
import roboguice.inject.InjectExtra;
import roboguice.inject.InjectPreference;
import roboguice.inject.InjectResource;
import roboguice.inject.NullProvider;
import roboguice.inject.PreferenceListener;
import roboguice.inject.ResourceListener;
import roboguice.inject.ResourcesProvider;
import roboguice.inject.SharedPreferencesProvider;
import roboguice.inject.SystemServiceProvider;
import roboguice.inject.ViewListener;
import roboguice.service.RoboService;
import roboguice.util.Ln;
import roboguice.util.LnImpl;
import roboguice.util.LnInterface;

import com.google.inject.Provider;
import com.google.inject.Provides;
import com.google.inject.Singleton;
import com.google.inject.AbstractModule;
import com.google.inject.matcher.Matchers;
import com.google.inject.name.Named;
import com.google.inject.name.Names;

import android.app.Activity;
import android.app.ActivityManager;
import android.app.AlarmManager;
import android.app.Application;
import android.app.DownloadManager;
import android.app.KeyguardManager;
import android.app.NotificationManager;
import android.app.SearchManager;
import android.app.Service;
import android.content.ContentResolver;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.hardware.SensorManager;
import android.location.LocationManager;
import android.media.AudioManager;
import android.net.ConnectivityManager;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.Build.VERSION;
import android.os.Handler;
import android.os.PowerManager;
import android.os.Vibrator;
import android.provider.Settings;
import android.provider.Settings.Secure;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;

/**
 * A Module that provides bindings and configuration to use Guice on Android.
 * Used by {@link roboguice.RoboGuice}.
 *
 * If you wish to add your own bindings, DO NOT subclass this class.  Instead, create a new
 * module that extends AbstractModule with your own bindings, then do something like the following:
 *
 * RoboGuice.setAppliationInjector( app, RoboGuice.DEFAULT_STAGE, Modules.override(RoboGuice.newDefaultRoboModule(app)).with(new MyModule() );
 *
 * @see com.google.inject.util.Modules#override(com.google.inject.Module...)
 * @see roboguice.RoboGuice#getOrCreateBaseApplicationInjector(android.app.Application, com.google.inject.Stage, com.google.inject.Module...)
 * @see roboguice.RoboGuice#newDefaultRoboModule(android.app.Application)
 * @see roboguice.RoboGuice#DEFAULT_STAGE
 *
 * @author Mike Burton
 */
@SuppressWarnings("PMD")
public class DefaultRoboModule extends AbstractModule {
    /**
     * Allows to retrieve the global, inter-context {@link EventManager}.
     * you MUST get the global {@link EventManager} either via a field annotated with {@code @Inject @Named}
     * or {@code getInjector.getInstance(key(EventManager.cass, Names.named())}.
     */
    public static final String GLOBAL_EVENT_MANAGER_NAME = "GlobalEventManager";

    @SuppressWarnings("rawtypes")
    private static Map<Class, String> mapSystemSericeClassToName = new HashMap<Class, String>();

    protected Application application;
    protected ContextScope contextScope;
    protected ResourceListener resourceListener;
    protected ViewListener viewListener;

    static {
        mapSystemSericeClassToName.put(LocationManager.class, Context.LOCATION_SERVICE);
        mapSystemSericeClassToName.put(WindowManager.class, Context.WINDOW_SERVICE);
        mapSystemSericeClassToName.put(ActivityManager.class, Context.ACTIVITY_SERVICE);
        mapSystemSericeClassToName.put(PowerManager.class, Context.POWER_SERVICE);
        mapSystemSericeClassToName.put(AlarmManager.class, Context.ALARM_SERVICE);
        mapSystemSericeClassToName.put(NotificationManager.class, Context.NOTIFICATION_SERVICE);
        mapSystemSericeClassToName.put(KeyguardManager.class, Context.KEYGUARD_SERVICE);
        mapSystemSericeClassToName.put(Vibrator.class, Context.VIBRATOR_SERVICE);
        mapSystemSericeClassToName.put(ConnectivityManager.class, Context.CONNECTIVITY_SERVICE);
        mapSystemSericeClassToName.put(WifiManager.class, Context.WIFI_SERVICE);
        mapSystemSericeClassToName.put(InputMethodManager.class, Context.INPUT_METHOD_SERVICE);
        mapSystemSericeClassToName.put(SensorManager.class, Context.SENSOR_SERVICE);
        mapSystemSericeClassToName.put(TelephonyManager.class, Context.TELEPHONY_SERVICE);
        mapSystemSericeClassToName.put(AudioManager.class, Context.AUDIO_SERVICE);
        if( VERSION.SDK_INT>=Build.VERSION_CODES.GINGERBREAD ) {
            mapSystemSericeClassToName.put(DownloadManager.class, Context.DOWNLOAD_SERVICE);
        }
    }

    public DefaultRoboModule(final Application application, ContextScope contextScope, ViewListener viewListener, ResourceListener resourceListener) {
        this.application = application;
        this.contextScope = contextScope;
        this.viewListener = viewListener;
        this.resourceListener = resourceListener;
    }

    /**
     * Configure this module to define Android related bindings.
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    @Override
    protected void configure() {

        final Provider<Context> contextProvider = getProvider(Context.class);
        final EventListenerThreadingDecorator observerThreadingDecorator = new EventListenerThreadingDecorator();

        // Singletons
        bind(ViewListener.class).toInstance(viewListener);

        // ContextSingleton bindings
        bindScope(ContextSingleton.class, contextScope);
        //we need to super bind as we inject the scope by code only, not by annotations
        superbind(ContextScope.class).toInstance(contextScope);
        bind(AssetManager.class).toProvider(AssetManagerProvider.class);
        bind(Context.class).toProvider(NullProvider.<Context>instance()).in(ContextSingleton.class);
        bind(Activity.class).toProvider(NullProvider.<Activity>instance()).in(ContextSingleton.class);
        bind(RoboActivity.class).toProvider(NullProvider.<RoboActivity>instance()).in(ContextSingleton.class);
        bind(Service.class).toProvider(NullProvider.<Service>instance()).in(ContextSingleton.class);
        bind(RoboService.class).toProvider(NullProvider.<RoboService>instance()).in(ContextSingleton.class);

        // Sundry Android Classes
        bind(SharedPreferences.class).toProvider(SharedPreferencesProvider.class);
        bind(Resources.class).toProvider(ResourcesProvider.class);
        bind(ContentResolver.class).toProvider(ContentResolverProvider.class);
        bind(Application.class).toInstance(application);
        bind(EventListenerThreadingDecorator.class).toInstance(observerThreadingDecorator);
        bind(EventManager.class).annotatedWith(Names.named(GLOBAL_EVENT_MANAGER_NAME)).to(EventManager.class).asEagerSingleton();
        bind(Handler.class).toProvider(HandlerProvider.class);

        // System Services
        for( Entry<Class, String> entry : mapSystemSericeClassToName.entrySet() ) {
            bindSystemService(entry.getKey(), entry.getValue());
        }

        // System Services that must be scoped to current context
        bind(LayoutInflater.class).toProvider(new ContextScopedSystemServiceProvider<LayoutInflater>(contextProvider,Context.LAYOUT_INFLATER_SERVICE));
        bind(SearchManager.class).toProvider(new ContextScopedSystemServiceProvider<SearchManager>(contextProvider,Context.SEARCH_SERVICE));

        // Android Resources, Views and extras require special handling
        if( hasInjectionPointsForAnnotation(InjectResource.class) ) {
            bindListener(Matchers.any(), resourceListener);
        }

        if( hasInjectionPointsForAnnotation(InjectExtra.class) ) {
            final ExtrasListener extrasListener = new ExtrasListener(contextProvider);
            bindListener(Matchers.any(), extrasListener);
        }

        //should be bound only if we use InjectView or InjectFragment
        bindListener(Matchers.any(), viewListener);

        final PreferenceListener preferenceListener = new PreferenceListener(contextProvider,application);
        superbind(PreferenceListener.class).toInstance(preferenceListener);
        if( hasInjectionPointsForAnnotation(InjectPreference.class) ) {
            bindListener(Matchers.any(), preferenceListener);
        }

        //should always be bound as ContentViewListener relies on event system
        bindListener(Matchers.any(), new ObservesTypeListener(getProvider(EventManager.class), observerThreadingDecorator));
        requestInjection(observerThreadingDecorator);

        if( isInjectable(Ln.class)) {
            bind(LnInterface.class).to(LnImpl.class);
            //should this be placed in if statement ?
            requestStaticInjection(Ln.class);
        }

        bindDynamicBindings();
    }

    private <T> void bindSystemService(Class<T> c, String androidServiceName) {
        bind(c).toProvider(new SystemServiceProvider<T>(application, androidServiceName ));
    }

    @SuppressWarnings("unchecked")
    private void bindDynamicBindings() {
        // Compatibility library bindings
        if(FragmentUtil.hasSupport) {
            bind(FragmentUtil.supportFrag.fragmentManagerType()).toProvider(FragmentUtil.supportFrag.fragmentManagerProviderType());
        }
        if(FragmentUtil.hasNative) {
            bind(FragmentUtil.nativeFrag.fragmentManagerType()).toProvider(FragmentUtil.nativeFrag.fragmentManagerProviderType());
        }

        if( VERSION.SDK_INT>=Build.VERSION_CODES.ECLAIR ) {
            try {
                @SuppressWarnings("rawtypes")
                Class c = Class.forName("android.accounts.AccountManager");
                bind(c).toProvider(AccountManagerProvider.class);
            } catch( Throwable ex ) {
                Log.e(DefaultRoboModule.class.getName(), "Impossible to bind AccountManager", ex);
            }
        }
    }

    // ----------------------------------
    //  PROVIDER METHODS
    //  used for lazy bindings, when
    //  instance creation is costly.
    // ----------------------------------

    @Provides
    @Singleton
    public PackageInfo providesPackageInfo() {
        try {
            return application.getPackageManager().getPackageInfo(application.getPackageName(),0);
        } catch( PackageManager.NameNotFoundException e ) {
            throw new RuntimeException(e);
        }
    }

    @Provides
    @Named(Settings.Secure.ANDROID_ID)
    public String providesAndroidId() {
        String androidId = null;
        final ContentResolver contentResolver = application.getContentResolver();
        try {
            androidId = Secure.getString(contentResolver, Secure.ANDROID_ID);
        } catch( RuntimeException e) {
            // ignore Stub! errors for Secure.getString() when mocking in test cases since there's no way to mock static methods
            Log.e(DefaultRoboModule.class.getName(), "Impossible to get the android device Id. This may fail 'normally' when testing.", e);
        }

        if(!"".equals(androidId)) {
            return androidId;
        } else {
            throw new RuntimeException("No Android Id.");
        }
    }

}
时间: 2024-11-08 22:16:43

【四】注入框架RoboGuice使用:(Your First System Service Injection)的相关文章

【九】注入框架RoboGuice使用:(Your First Injected Service and BroadcastReceiver)

上一篇我们简单的介绍了一下RoboGuice的使用([八]注入框架RoboGuice使用:(Your First Injected Fragment)),今天我们来看下服务(Service)和广播接受者(BroadCast Receiver)的注入 (一):和Robo*Activities一样,RoboServices和RoboIntentServices通过RoboGuice也自动接受注入. 下面是一个使用RoboGuice注入的android service的例子: public class

【十四】注入框架RoboGuice使用总结

在我们平时开发Android项目的时候例如经常需要使用各种View控件,然后进行声明,findViewById,并且进行强转.每次都要写这样的代码就显得非常繁琐,并且容易出错哦.那么针对这种情况且不限定于以上的这类情况,Dependency injection 可以大大降低了类之间的依赖性,可以通过annotation (Java)描述类之间的依赖性,避免了直接调用类似的构造函数或是使用Factory来参加所需的类,从而降低类或模块之间的耦合性,以提高代码重用并增强代码的可维护性.Google

【五】注入框架RoboGuice使用:(Your First POJO Injection)

上一篇我们简单的介绍了一下RoboGuice的使用([四]注入框架RoboGuice使用:(Your First System Service Injection)),今天我们来看下普通Java对象的使用注解的方法: (一)为了在Activity中普通Java对象使用注解,必须实现以下两个步骤: ①:创建继承RoboActivity的Activity ②:使用 @Inject来进行注解POJO(普通java对象) 在前面我们介绍了View控件,资源文件(Resources),系统服务(Syste

【十】注入框架RoboGuice使用:(Your First Testcase)

上一篇我们简单的介绍了一下RoboGuice的使用([九]注入框架RoboGuice使用:(Your First Injected Service and BroadcastReceiver)),今天我们来看下测试用例(TestCase)的注入 RoboGuice使得我们更加容易实现可测试的Android应用程序,本文章就来详细解说下:当我们测试的时候,如何编写测试用例,已经从RoboGuice中获益.本文章使用Android Robolectric,适合大部分用Android标准测试的情况.

【十三】注入框架RoboGuice使用:(Logging via Ln)

上一篇我们简单的介绍了一下RoboGuice的使用([十二]注入框架RoboGuice使用:(Your First Injected ContentProvider)),今天我们来看下Log日志使用. Android应用通过会使用内置的android.util.log在Android控制台上面打印日志信息.RoboGuice也提供了另外的日志管理,你可能会想要使用. (一):  RoboGuice日志管理和通常的Log差不多,但也同样具备以下优点: ①:对于发布包来说,Debug and ver

【六】注入框架RoboGuice使用:(Singletons And ContextSingletons)

上一篇我们简单的介绍了一下RoboGuice的使用([五]注入框架RoboGuice使用:(Your First POJO Injection)),今天我们来看下单例以及上下文单例(ContextSingletons)使用注解的方法,从上一篇文章中相信大家对于普通Java对象(POJO)注解已经很熟悉了. (一)概述:简要使用方法 ①:创建继承RoboActivity的Activity类 ②:使用@Inject进行注解POJO(普通Java对象) ③:使用@Singleton进行注解POJO类

【十二】注入框架RoboGuice使用:(Your First Injected ContentProvider)

上一篇我们简单的介绍了一下RoboGuice的使用([十一]注入框架RoboGuice使用:(Your First Injection into a Custom View class)),今天我们来看下内容提供者(ContentProvider)的注入. 和Robo*Activities一样,RoboContentProviders通过RoboGuice也能自动获得注入,为了简便我们可以注入 authority URI,这时我们需要定义下面自己的module: public class Con

【十一】注入框架RoboGuice使用:(Your First Injection into a Custom View class)

上一篇我们简单的介绍了一下RoboGuice的使用([十]注入框架RoboGuice使用:(Your First Testcase)),今天我们来看下自定义View的注入(Custom View). 在开始本文之前,你先要熟悉普通Java对象的注入(点击进入).在RoboGuice 3.0版本中你同样给自定义View(Custom View)进行诸如. class MyView extends View { @Inject Foo foo; @InjectView(R.id.my_view) T

【二】注入框架RoboGuice使用:(Your First View Injection)

上一篇我们简单的介绍了一下RoboGuice的使用([一]注入框架RoboGuice使用:(A brief example of what RoboGuice does)),今天我们我看下View的注解的使用方法. 为了在Activity中使用View的注解,必须实现以下三个步骤: ①:自己定义的Activity继承RoboActivity ②:设置内容视图 content View ③:使用 @InjectView来进行注解View控件 下面我们来详细看一下使用方法: (一)首先创建一个继承与