This is my Main App
public class MainApp extends Application {
private MainComponent component;
private static Context context;
public MainApp() {
this.component = initDagger();
context = getApplicationContext();
}
public MainComponent getComponent() {
return component;
}
public static Context getContext() {
return context;
}
private MainComponent initDagger() {
return DaggerMainComponent.builder().build();
}
}
In main activity I use these codes below and receive an error
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
unbinder = ButterKnife.bind(this);
((MainApp) getApplication()).getComponent().inject(this);
// presenter = new MainActivityPresenter();
presenter.attachView(this);
}
This is the error that I received. It said that I cannot cast Application to MainApp. But I follow dagger example and I see that they do this and it works.
What is the problem with my code
Caused by: java.lang.ClassCastException: android.app.Application cannot be cast to com.example.huytrinh.sampledagger.MainApp
at com.example.huytrinh.sampledagger.MainActivity.onCreate(MainActivity.java:39)
at android.app.Activity.performCreate(Activity.java:5360)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1088)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2336)
In Manifest add your name to application tag
<application
android:name=".MainApp"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme">
1.Your are getting exception because you dint include the custom application class in manifest.Add the class in manifest like this.
<application
android:name=".MainApp"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
2.Create dagger class and other things only after application is created i.e in oncreate of the application class
#Override
public void onCreate() {
super.onCreate();
this.component = initDagger();
context = getApplicationContext();
}
Try this.
First
To get MainApp
private static MainApp instance;
public
static MainApp getInstance() {
return instance;
}
#Override
public void onCreate() {
super.onCreate();
instance = this;
}
Second
MainApp.getInstance().getComponent().inject(this);
Edit
<application
android:name=".MainApp"
... />
Related
I need to call certain non static methods in an activity when the user interacts with buttons in notification, I tried to do it in a standalone class the extends BroadcastReceiver it works, but I don't know how call a method on the activity mentioned earlier, I tried to make an inner class, non static, edited the manifest file it was first :
<receiver android:name=".Activity$NotificationBroadcast" >
<intent-filter>
.
.
.
</intent-filter>
</receiver>
and that gives me an error saying :
FATAL EXCEPTION: main
Process: com.example.app, PID: 3189
java.lang.RuntimeException: Unable to instantiate receiver
com.example.app.Activity$NotificationBroadcast:
java.lang.InstantiationException:
the class is :
public class NotificationBroadcast extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent){
if (intent.getAction().equals(Activity.ACTION1)){
// do things
} else if (intent.getAction().equals(Activity.ACTION1)){
// do things
}else if (intent.getAction().equals(Activity.ACTION2)){
// do things
}else if (intent.getAction().equals(Activity.ACTION3)){
// do things
}else if (intent.getAction().equals(Activity.ACTION4)){
// do things
}
}
}
I'm afraid you can't make the receiver as an inner class, because when the receiver is statically instantiated, the "holder" class has to be instantiated as well. The activity instance is only created when it is meant to be active, and that's why you got the exception.
If you want the receiver to interact with the activity (by calling non-static methods in the activity class), I suggest that you should make the receiver a non-static one. This means that you need to register an instance of the receiver in OnCreate() and unregister it in OnDestroy().
For a better design, the activity instance should be passed into the receiver via its constructor as an interface, so that the receiver does not get access to the whole activity object, but is only able to access the functionality.
Manifest should have:
<receiver android:name=".NotificationBroadcast" android:enabled="false" />
An interface for the interaction (IWorker.java for example):
public interface IWorker {
public void doThis();
public void doThat();
}
The receiver (a class on its own) takes the IWorker and does something when a broadcast is received:
public class NotificationReceiver extends BroadcastReceiver {
public static final string ACTION1 = "com.yourpackage.action1";
public static final string ACTION2 = "com.yourpackage.action2";
private IWorker worker;
public NotificationReceiver() {
}
public NotificationReceiver(IWorker worker) {
this.worker = worker;
}
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION1)) {
worker.doThis();
} else if (intent.getAction().equals(ACTION2)) {
worker.doThat();
}
}
}
And the activity takes care of the receiver on its life cycle:
public class MyActivity extends Activity implements IWorker {
private NotificationReceiver receiver;
#override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// create the receiver
receiver = new NotificationReceiver(this);
IntentFilter filter = new IntentFilter();
filter.addAction(NotificationReceiver.ACTION1);
filter.addAction(NotificationReceiver.ACTION2);
// register it
registerReceiver(receiver, filter);
}
#override
protected void onDestroy() {
super.onDestroy();
if (receiver != null) {
unregisterReceiver(receiver);
receiver = null;
}
}
#override
public void doThis() {
System.out.println("Doing this...");
}
#override
public void doThat() {
System.out.println("Doing that...");
}
}
P.S. The above codes are for reference only, they're not tested and may not compile.
How can I use findViewById() in a non activity class. Below is my code snippet. I get the error message: "can't resolve method findViewById" if used directly. And if i try to use the class constructor (Where the imageView is available) i get this error "cannot resolve symbol context"
public class MyBroadcastReceiver extends FirstBroadcastReceiver {
Activity activity;
public MyBroadcastReceiver(Context context, Activity activity){
this.context=context; // error here(cannot resolve symbol context)
this.activity=activity;
}
#Override
protected void (Context context) {
// content
}
#Override
public void onButton(Context context, boolean isClick) {
if(isClick) {
ImageView blueImage = (ImageView)activity.findViewById(R.id.imageView);
blueImage.setColorFilter(0xff000000);
}
}
.......
....
// and so on
And below is my MainActivity with MybroadcastReceiver class instance.Is it correct?
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// and so on
}
}
MyBroadcastReceiver myBroadcastReceiver = new MyBroadcastReceiver(MainActivity.this,this);
#Override
public void onActivityResult() {
// some code
}
#Override
public void onInitialized(MyManager manager){
// some code
}
A BroacastReceiver runs entirely in the background, listening for Intents sent either by the OS or other apps. It is not responsible for any UI interactions, and cannot access any views. Therefore, findViewById cannot be used within a BroadcastReceiver.
See also - What is BroadcastReceiver and when we use it?
You have to pass View to the non activity class, before using findViewByid
and
try using
view.findViewByid(R.id.view_id);
Because context is null in Broadcast class. use Broadcast class constructor to pass parent_activity(Where the imageView is available) context in Broadcast to access the context:
public class Broadcast extends BroadCastReceiver {
Activity activity;
public Broadcast(Context context,Activity activity){
this.context=context;
this.activity=activity;
}
.......
....... //so on
and in parent_activity create Broadcast class instance by passing parent_activity context as:
Broadcast broadcast = new Broadcast(parent_activity.this,this);
Use activity instance as:
#Override
public void onButton(Context context, boolean isClick) {
if(isClick) {
ImageView blueImage = (ImageView) activity.findViewById(R.id.imageView); //<--- here
}
}
.........
......... //so on
public class QRProductActivityPageObject {
public static void testProductDetail() throws InterruptedException {
ActivityTestRule<ProductInfoActivity> rule = new ActivityTestRule<ProductInfoActivity>(ProductInfoActivity.class, true, false);
Intent intent = new Intent();
intent.setClass(getActivity(), ProductInfoActivity.class);
rule.launchActivity(intent);
Thread.sleep(2000);
}
}
The above syntax show error that you cant access getActivity() in static method .
But i want to call this new Activity(ProductInfoActivity) through static method only.Any suggestion??
Pass context when method call in Activity or fragment and get Activity from context in static method
public static void testProductDetail(Context context) throws InterruptedException {
ActivityTestRule<ProductInfoActivity> rule = new ActivityTestRule<ProductInfoActivity>(ProductInfoActivity.class, true, false);
Intent intent = new Intent();
Activity activity = (Activity) context;
intent.setClass(activity , ProductInfoActivity.class);
rule.launchActivity(intent);
Thread.sleep(2000);
}
Call static method In activity
testProductDetail(getApplicationContext());
In fragment
testProductDetail(getActivity().getApplicationContext());
Or use the solution I found around here a few weeks ago, it's pretty awesome and elegant. You'd be able to use it anywhere in your APP!
Create a class MyApplication (you could name it differently):
public class MyApplication extends Application {
private static Context context;
public void onCreate() {
super.onCreate();
MyApplication.context = getApplicationContext();
}
public static Context getAppContext() {
return MyApplication.context;
}
}
Go to your app Manifest file and add to the <application... tag the android:name attribute with the value of the name of the class we created:
<application
android:allowBackup="true"
android:icon="#drawable/appico"
android:label="#string/app_name"
android:name="MyApplication"
Now you can get the context for your app from any class like that
MyApplication.getAppContext();
You don't need to call getActivity(). Instead of using setClass() method which requires you to give a context object, you can use setClassName(String packageName, String className) method. Try this:
Intent intent = new Intent();
intent.setClassName("package.name.of.your.app",
ProductInfoActivity.class.getName());
I try to implement the Google Analytics in my App.
The Problem is I get in LogCat the message:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.name.appname/com.name.appname.activity.MainActivity}: java.lang.ClassCastException: com.name.appname.misc.AppApplication cannot be cast to com.name.appname.activity.Analytics
global_tracker.xml
<integer name="ga_sessionTimeout">300</integer>
<!-- Enable automatic Activity measurement -->
<bool name="ga_autoActivityTracking">true</bool>
<!-- Enable verbose logging -->
<String name="ga_loglevel">verbose</String>
<!-- Screen names on the reports -->
<screenName name="com.name.appname.activity.MainActivity">
MainActivity ScreenView
</screenName>
<!-- Tracking ID -->
<string name="ga_trackingId">UA-xxxxxxx-2</string>
ANALytics.java:
public class Analytics extends Application {
public static int GENERAL_TRACKER = 0;
public enum TrackerName {
APP_TRACKER, // Tracker used only in this app.
GLOBAL_TRACKER, // Tracker used by all the apps from a company. eg: roll-up tracking.
ECOMMERCE_TRACKER, // Tracker used by all ecommerce transactions from a company.
}
HashMap<TrackerName, Tracker> mTrackers = new HashMap<TrackerName, Tracker>();
synchronized Tracker getTracker(TrackerName trackerId) {
if (!mTrackers.containsKey(trackerId)) {
GoogleAnalytics analytics = GoogleAnalytics.getInstance(this);
Tracker t = analytics.newTracker(R.xml.global_tracker);
mTrackers.put(trackerId, t);
}
return mTrackers.get(trackerId);
}
}
manifest:
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme"
android:name=".misc.AppApplication" >
<activity
android:name=".activity.Analytics"
android:allowBackup="true"
android:label="#string/app_name"
android:screenOrientation="portrait" >
</activity>
MainActivity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
adView = (AdView) this.findViewById(R.id.adView);
// Get tracker.
Tracker tracker = ((Analytics)getApplication()).getTracker(Analytics.TrackerName.GLOBAL_TRACKER);
tracker.send(new HitBuilders.EventBuilder()
.setCategory("Use")
.setAction("Use Programm")
.setLabel("submit")
.build());
#Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
GoogleAnalytics.getInstance(MainActivity.this).reportActivityStart(this);
}
#Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
GoogleAnalytics.getInstance(MainActivity.this).reportActivityStop(this);
}
In my manifest i have already declared android:name=".misc.AppApplication" at application. there is my check for PremiumUsers.
Here is my misc.AppApplication:
import android.app.Application;
public class AppApplication extends Application {
private boolean mIsPremium;
public void setPremium(){
mIsPremium = true;
}
public boolean isPremium(){
return mIsPremium;
}
}
where is the problem?
You are setting the name attribute of your application element in the manifest to ".misc.AppApplication". That instructs Android to instantiate .misc.AppApplication class as application instead of the default Application. In your MainActivity class you try to cast .misc.AppApplication to Analytics and that will throw ClassCastException.
The correct setup is to replace the Application class with Analytics (the class that extends Android Application class) and keep MainActivity as the class implementing your main activity.
You should also not be logging events from onCreate override. Activity can be created for reasons other then starting the app. For example when the device changes from landscape to portrait mode Android will ask the activity to save its state to a bundle, tear it down and recreate it passing the saved state in savedInstanceState. onCreate will be called in this case again.
Need your help!
How do I in my application to call the function only once when opening?
I do:
private boolean is_first = true;
#Override
public void onCreate(Bundle savedInstanceState) {
if ( is_first ) {
MyFirstFunction();
}
}
public void onResume(Bundle savedInstanceState) {
super.onResume();
is_first = false;
}
Also in the manifest file added to the activity android:configChanges="orientation" but still function when you turn the device restarts
I hope for your help!
you can use Application class to do that in the onCreate method you can call your function
public class MyApp extends Application {
#Override
public void onCreate() {
//this will be called each time you open the application
super.onCreate();
//call you function here
}
}
then add this class to the manifest
<application
android:name=".MyApp or your class name"
......
....>