2016-12-09 3 views
2

У меня есть класс приложений, как это:ApplicationContext в BroadcastReceiver

public class MyApplication extends Application { 
} 

Он зарегистрирован в манифесте:

<application 
     android:name=".MyApplication" 
     android:allowBackup="true" 
     android:icon="@mipmap/ic_launcher" 
     android:label="@string/app_name" 
     android:supportsRtl="true" 
     android:theme="@style/AppTheme"> 
    ... 

    </application> 

Я использую этот класс приложений для хранения компонентов Dagger и т.д.

Сейчас у меня есть BroadcastReceiver:

public class MyBroadcastReceiver extends BroadcastReceiver { 
    @Override 
    public void onReceive(final Context context, final Intent intent){ 

     MyApplication myApplication = (MyApplication) context.getApplicationContext();   
    } 
} 

Он зарегистрирован в Manifest как InstallReferrerReceiver:

<receiver 
     android:name="my.package.MyReceiver" 
     android:exported="true"> 
     <intent-filter> 
      <action android:name="com.android.vending.INSTALL_REFERRER"/> 
     </intent-filter> 
    </receiver> 

Как вы можете видеть, что я бросил контекст приложения для моего класса Application, который прекрасно работает в деятельности и т.д., а также, как правило, здесь.

Via Crashlytics хотя я получаю исключение:

Unable to start receiver my.package.BroadcastReceiver: java.lang.ClassCastException: android.app.Application cannot be cast to my.package.MyApplication 

Мой вопрос заключается в том: я негарантированно получить свой объект Application в контексте приложения в BroadcastReceiver?

+0

Это должно работать нормально. Существуют ли какие-либо общие черты между устройствами, сообщающими об этом сбое? Кроме того, есть ли что-нибудь необычное в элементе '' (например, вы используете 'android: process') или как передается трансляция? – CommonsWare

+1

Я думаю, что у вас нет гарантированного доступа к вашему приложению в вашем «BroadcastReceiver» (я ищу источник). Вы можете проверить 'if (context.getApplicationContext() instanceof MyApplication)? –

+0

@CommonsWare К сожалению, это было, вероятно, важно добавить, я добавил запись манифеста для получателя. – FWeigl

ответ

1

Если вы посмотрите на реализацию ActivityThread.handleReceiver, вы увидите, что BroadcastReceiver.onReceived вызывается путем передачи ContextImpl.getReceiverRestrictedContext(). Контекст, возвращаемый этим вызовом, фактически не переносит getApplicationContext, поэтому ti будет вызван в ContextImpl. Теперь, если вы посмотрите на ContextImpl.getApplicationContext(), вы увидите что-то вроде этого

@Override 
public Context getApplicationContext() { 
    return (mPackageInfo != null) ? mPackageInfo.getApplication() : 
     mMainThread.getApplication(); 
} 

Если посмотреть на последней ветви троичного оператора вы увидите, что он перезвонит ActivityThread.getApplication() который вернет его mInitialApplication участник. mInitialApplication инициализируется вызовом LoadedApk.makeApplication(), который имеет логический параметр: forceDefaultAppClass. Если установлено значение true, то android.app.Application создаст экземпляр вместо приложения, определенного в вашем манифесте.

на основе AOSP источника это происходит, когда для например .:

Если приложение быть запущен для полного резервного копирования и восстановления, довести его до в ограниченной среде с базовым классом приложений.