Call method in MainActivity class from another class - java

What I want to do is call a method which is placed in my MainActivity.java file from another subclass. But everytime i want to call this method, my app crashes.
I already tried to make SetGerateStat() static but that didn't change anything. Also, I can build the apk without any errors, the application only crashes when the SetGerateStat() is called from the Thread.
What am I doing wrong here?
My code is below (please note that this is only a snippet):
MainActivity.java:
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private CheckedTextView gerätestat;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void setGeraeteStat(boolean x) {
if (x==true) {
gerätestat.setCheckMarkDrawable(android.R.drawable.presence_online);
} else {
gerätestat.setCheckMarkDrawable(android.R.drawable.presence_busy);
}
}
public void onClick(View v) {
if(v==button_refresh) {
Thread connection = new Thread(new Conn("refresh", MainActivity.this));
connection.start();
}
}
Conn.java:
public class Conn implements Runnable {
private MainActivity act;
private String actioncommand;
public Conn(String a) {
actioncommand = a;
act = null;
}
public Conn(String a, MainActivity m) {
actioncommand = a;
act = m;
}
public void run() {
switch(actioncommand) {
case "refresh": {
act.setGeraeteStat(true);
}
break;
}
}

Have you forgot to initialize gerätestat ? You have to initialize gerätestat after setcontentview. After that use runOnUIThread method as below
public void setGeraeteStat(final boolean x){
runOnUiThread (new Runnable() {
public void run() {
if (x==true) {
gerätestat.setCheckMarkDrawable(android.R.drawable.presence_online);
} else {
gerätestat.setCheckMarkDrawable(android.R.drawable.presence_busy);
}
}
});}

Related

How to detect application runs foreground or background using Single Activity or Java class

I want to sent report to the server which means how long user Use the application in single day..I can achieve using this to method
#Override
protected void onResume() {
super.onResume();
//commonclassMethod.getInstance(UserForground);
}
#Override
protected void onStop() {
super.onStop();
//commonclassMethod.getInstance(UserBackground);
}
What happen i need to call call this method in every activity....
What i need,is there any possible to find user forground background method in single java class or activity..
Thanks in Advance.
You can can achieve this just by adding an method isAppIsInBackground(Context context) in class which is extending Application class
In that class define that method:
public static boolean isAppIsInBackground(Context context) {
boolean isInBackground = true;
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT_WATCH) {
List<ActivityManager.RunningAppProcessInfo> runningProcesses = am.getRunningAppProcesses();
for (ActivityManager.RunningAppProcessInfo processInfo : runningProcesses) {
if (processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
for (String activeProcess : processInfo.pkgList) {
if (activeProcess.equals(context.getPackageName())) {
isInBackground = false;
}
}
}
}
} else {
List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);
ComponentName componentInfo = taskInfo.get(0).topActivity;
if (componentInfo.getPackageName().equals(context.getPackageName())) {
isInBackground = false;
}
}
return isInBackground;
}
It will true if app is in background
Or another better approach would be just extend your each Activity by an BaseActivity, in this BaseActivity's override methods
protected void onResume() {
super.onResume();
//commonclassMethod.getInstance(UserForground);
}
protected void onStop() {
super.onStop();
//commonclassMethod.getInstance(UserBackground);
}
You can implement callback method to solve your case.
For example:
You create an interface first, then define a method, which would act as a callback. In this example we would have two classes, one classA and another classB
Interface:
public interface OnCustomEventListener{
public void onEvent(); //method, which can have parameters
}
the listener itself in classB (we only set the listener in classB)
private OnCustomEventListener mListener; //listener field
//setting the listener
public void setCustomEventListener(OnCustomEventListener eventListener) {
this.mListener=eventListener;
}
in classA, how we start listening for whatever classB has to tell
classB.setCustomEventListener(new OnCustomEventListener(){
public void onEvent(){
//do whatever you want to do when the event is performed.
}
});
how do we trigger an event from classB (for example on button pressed)
if(this.mListener!=null){
this.mListener.onEvent();
}
Here is some nice tutorials link1,link2,link3 which describes callbacks and the use-case well.
Create a class extending application and use registerActivityLifecycleCallbacks() to get the activity lifecycle
public class MyApp extends Application {
#Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
#Override
public void onActivityCreated(Activity activity, Bundle bundle) {
}
#Override
public void onActivityStarted(Activity activity) {
}
#Override
public void onActivityResumed(Activity activity) {
}
#Override
public void onActivityPaused(Activity activity) {
if(activity.getClass().getSimpleName().equalsIgnoreCase(MainActivity.class.getSimpleName())){
//Do the required thing here
}
}
#Override
public void onActivityStopped(Activity activity) {
}
#Override
public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {
}
#Override
public void onActivityDestroyed(Activity activity) {
}
});
}
}
Also dont forget to register activity in manifest
<application
android:name=".MyApp"
You have two options.
1) Do a abstract BaseActivity and make all Activities extend it. This way you only write the code in one BaseActivity and all children activities consume it.
2) Use a custom counter class to monitor app to foreground. Here is my implementation of it if you would like to copy it.
/**
* Created by App Studio 35 on 6/23/17.
*/
public class AppLifeCycleTracker implements Application.ActivityLifecycleCallbacks {;
/*///////////////////////////////////////////////////////////////
// METHODS
*////////////////////////////////////////////////////////////////
private static final String TAG = Globals.SEARCH_STRING + AppLifeCycleTracker.class.getSimpleName();
private static AppLifeCycleTracker INSTANCE;
private static int numActivitiesInMemory = 0;
private ArrayList<IAppToForegroundListener> mAppToForegroundListeners;
private boolean isRefreshing;
private Object lockAccess = new Object();
private AlertDialog mAlertDialog = null;
/*///////////////////////////////////////////////////////////////
// PROPERTIES
*////////////////////////////////////////////////////////////////
private ArrayList<IAppToForegroundListener> getAppToForegroundListeners(){
return mAppToForegroundListeners == null ? mAppToForegroundListeners = new ArrayList<IAppToForegroundListener>() : mAppToForegroundListeners;
}
public boolean getIsRefreshing(){
return isRefreshing;
}
public boolean getAppIsInBackground(){
return numActivitiesInMemory < 1;
}
/*///////////////////////////////////////////////////////////////
// CONSTRUCTOR
*////////////////////////////////////////////////////////////////
private AppLifeCycleTracker(){
}
public synchronized static AppLifeCycleTracker getInstance(){
if(INSTANCE == null){
INSTANCE = new AppLifeCycleTracker();
}
return INSTANCE;
}
/*///////////////////////////////////////////////////////////////
// LIFE CYCLE OVERRIDES
*////////////////////////////////////////////////////////////////
#Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
#Override
public void onActivityStarted(final Activity activity) {
//App went into background, so set a flag to avoid loading while we refresh
if(numActivitiesInMemory == 0 && !(activity instanceof SplashScreenActivity) && !(activity instanceof CreateAccountActivity)){
A35Log.v(TAG, "App Returned to Foreground, refreshing Token");
//first load on splash it goes from 0 to 1 so hold off on splash
synchronized (lockAccess) {
isRefreshing = true;
}
if (DeviceInfo.getInstance(activity).getIsConnectedToInternet()) {
CognitoManager.refreshToken(activity, new GenericHandler() {
#Override
public void onSuccess() {
A35Log.v(TAG, "Token Refresh Complete, notifying listeners");
//we are good, keep going
for(IAppToForegroundListener listener : getAppToForegroundListeners()){
listener.onRefreshTokenComplete();
}
synchronized (lockAccess) {
isRefreshing = false;
}
}
#Override
public void onFailure(Exception exception) {
//boot them to login screen
if(activity instanceof LoginActivity || activity instanceof SplashScreenActivity){
return;
}
startLoginActivity(activity);
synchronized (lockAccess) {
isRefreshing = false;
}
}
});
} else {
showInternetRequiredDialog(activity);
}
}
numActivitiesInMemory++;
}
#Override
public void onActivityResumed(Activity activity) {
}
#Override
public void onActivityPaused(Activity activity) {
}
#Override
public void onActivityStopped(Activity activity) {
numActivitiesInMemory--;
//if numActivities == 0 then you are in the background
}
#Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
#Override
public void onActivityDestroyed(Activity activity) {
}
/*///////////////////////////////////////////////////////////////
// METHODS
*////////////////////////////////////////////////////////////////
public void addAppToForegroundListener(IAppToForegroundListener listener){
getAppToForegroundListeners().add(listener);
}
public void removeAppToForegroundListener(IAppToForegroundListener listener){
getAppToForegroundListeners().remove(listener);
}
private void startLoginActivity(final Activity activity){
((AMApplication) activity.getApplication()).logoutCurrentUser(activity, false, false, null, true, null);
}
/*///////////////////////////////////////////////////////////////
// INTERFACES
*////////////////////////////////////////////////////////////////
public interface IAppToForegroundListener {
/*///////////////////////////////////////////////////////////////
// METHODS
*////////////////////////////////////////////////////////////////
void onRefreshTokenComplete();
}
private void showInternetRequiredDialog(Activity activity){
final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle("Error").setMessage("Internet is required to use this app").setNegativeButton(R.string.ok, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if(mAlertDialog != null && mAlertDialog.isShowing()) {
mAlertDialog.dismiss();
}
}
});
mAlertDialog = builder.create();
mAlertDialog.show();
}
}
Of course this does a little more then you are looking for as mine manages refreshing the token with cognito and forcing refresh on returning from background and things like that, so just disregard that piece. But the rest is all the same still. Hope that helps.
I'm assuming you don't need an example of a BaseActivity so I won't patronize you by pasting that.
Startup in Application class
#Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(AppLifeCycleTracker.getInstance());
}
Then you ONLY need to access from BaseActivity or BaseFragment IF you need to be notified when the app is in foreground or background at an Activity or fragment level. Which for your situation is not the case.
But if you ever wanted to use it, simply do this:
#Override
public void onAttach(Context context) {
super.onAttach(context);
AppLifeCycleTracker.getInstance().addAppToForegroundListener(this);
}
#Override
public void onDetach() {
super.onDetach();
AppLifeCycleTracker.getInstance().removeAppToForegroundListener(this);
}
But again, I must emphasize, this part is ONLY if you care to make your activity or fragment be aware of when the app comes back to foreground to force refresh or other behaviors. Replace onDetach with onDestroy if using Activity, but for your scenario you can skip that whole last section of code, you don't need it.

Listener doesn't work..It seems the Listener is 0

Hey Guys I have this as MainActivity:
public class LoginActivity extends AppCompatActivity {
public interface LoginListener {
public void onLoginSuccess();
}
public void onLoginSuccess() {
//logged in and do a few other things
}
}
And that's my second Activity from where I want to call the method onLoginSuccess() in my MainActivity, as you can see I am doing this with an Listener...
public class FingerprintHandler extends FingerprintManager.AuthenticationCallback {
private LoginActivity.LoginListener mListener;
public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
if (mListener != null) {
mListener.onLoginSuccess();
}
else{
Toast.makeText((Activity)context, "Listener is 0", Toast.LENGTH_LONG).show();
}
}
}
MY problem is that I everytime I try it I get back: "Listener is 0" from my Toast...SO what's wrong?
Extension of my comment above:
You need to register the mListener somehow. A pattern to do this is:
public class MyHandler {
private LoginListener mListener;
public MyHandler(LoginListener listener) {
mListener = listener;
}
// ... etc...
}
Where LoginListener is:
public interface LoginListener {
public void onLoginSuccess();
}
And your activity has:
public MyActivity implements LoginListener {
// instantiate the handler somewhere, with a reference
// to "this". "this" refers to the LoginListener interface
// which is implemented.
#Override
public void onCreate(Bundle b) {
mHandler = new MyHandler(this);
}
#Override
public void onLoginSuccess() {
Log.i(TAG, "Kewel beanZ");
}
}
Or, you can define LoginListener as an interface inside the activity if you wish, and instantiate it as:
public LoginListener mListener = new LoginListener() {
#Override
public void onLoginSuccess() {
Log.i(TAG, "Sweet sweet baby beanz");
}
};
And instead of using this, use mListener, when you create MyHandler.
Check below code for Fingerprint authentication in Android
https://gist.github.com/Evin1-/6aca8421903acca0e927eaefd85bd617

Android Callback Error

I want to make a callback function in the ShipInfoManager to inform the MainActivity to do some action.
If I put onEvent() into Runnable, it runs.
However If I put it like this, it shows an error.
Is there any way to fire the callback after loading data?
Or, is there any way to do the callback like Android's API's LocatioManger's requestLocationUpdates, giving a callback when the data/variables is changed?
Thank you for any replies!
MyCallback Interface:
interface MyCallback {
void callbackCall();
}
ShipInfoManager class:
public class ShipInfoManager {
Context mContext;
public ShipInfoManager(Context _mContext) {
this.mContext = _mContext;
reloadData();
startTimer();
}
MyCallback callback;
void onEvent() {
callback.callbackCall();
}
private void startTimer() {
/* RUN EVERY MIN */
final Handler handler = new Handler();
Timer timer = new Timer();
TimerTask doAsynchronousTask = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
#SuppressWarnings("unchecked")
public void run() {
try {
reloadData();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
};
// TEMP SUSPEND FROM PREVENTING RELOAD //
timer.schedule(doAsynchronousTask, 0, 5000);
}
/* JSON handling and extraction */
private void reloadData() {
//Do sth to reload the data
//After reload, I want to fire the callback
onEvent();
}
}
It looks like you haven't any listeners to your callback and you're not checking for this.
You should replace your ShipInfoManager with this:
public class ShipInfoManager {
public interface MyCallback {
void callbackCall();
}
public void setCustomEventListener(MyCallback eventListener) {
callback = eventListener;
}
Context mContext;
public ShipInfoManager(Context _mContext) {
this.mContext = _mContext;
reloadData();
startTimer();
}
MyCallback callback;
void onEvent() {
// Check if we have listeners
if (callback != null)
callback.callbackCall();
}
private void startTimer() {
/* RUN EVERY MIN */
final Handler handler = new Handler();
Timer timer = new Timer();
TimerTask doAsynchronousTask = new TimerTask() {
#Override
public void run() {
handler.post(new Runnable() {
#SuppressWarnings("unchecked")
public void run() {
try {
reloadData();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
};
// TEMP SUSPEND FROM PREVENTING RELOAD //
timer.schedule(doAsynchronousTask, 0, 5000);
}
/* JSON handling and extraction */
private void reloadData() {
//Do sth to reload the data
//After reload, I want to fire the callback
onEvent();
}
}
Inside your Activity or Fragment you should have something like:
public class MainActivity extends ActionBarActivity implements ShipInfoManager.MyCallback {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ShipInfoManager s = new ShipInfoManager(this);
s.setCustomEventListener(this);
}
#Override
public void callbackCall() {
}
}
I changed my MainActivity like this. It works now.
Thank you for your suggestion and reply!!!!!
public class MainActivity extends ActionBarActivity {
ShipInfoManager mShipInfo;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mShipInfo = new ShipInfoManager(this);
Log.i("Show Ship List Size", String.valueOf(mShipInfo.get_shipsList().size()));
Log.i("Show Ship - 6", String.valueOf(mShipInfo.getShip(6).getShip_name()));
mShipInfo.callback = new ShipInfoManager.MyCallback() {
#Override
public void callbackCall() {
Log.i("Call Back", "it is called");
}
};
}

Access variable in main activity from a thread

I have the following code:
public class MainActivity extends Activity {
public String myString;
...
public void updateString()
{
new Thread() {
#Override
public void run() {
this.myString = "TEST";
}
}
}
}
The problem is that I need to update myString from the thread, but I can't access it. Any suggestions? Thank you!
You can do in this way make string global and update it.
public class MainActivity extends Activity {
public String myString;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
updateString();
}
public void updateString()
{
new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
for(int i=0; i<10;i++){
myString=String.valueOf(i);
//log
Log.d("myString:",myString);
}
}
}).start();
}
In such cases create a custom class which would implement Runnable and pass myString as an argument to the constructor of the class, so when runnable object will be created, it would stored locally which can be accesed from run method whenever required.
You could use getters and setters, for example:
public class MainActivity extends Activity {
public String myString;
...
public void updateString()
{
new Thread() {
#Override
public void run() {
setMyString("TEST");
}
}
}
public void setMyString(String myString){
this.myString = myString;
}
}

andengine Google Plus Sign Button

I am trying to impement Google Plus Sign Button on my android application that uses andengine and I am getting a NullPointException.
Here is my code
public class GameActivity extends BaseGameActivity implements ConnectionCallbacks, OnConnectionFailedListener{
public static GameActivity gameActivity;
public static ProgressDialog mConnectionProgressDialog;
public static PlusClient mPlusClient;
public static ConnectionResult mConnectionResult;
private static final int REQUEST_CODE_RESOLVE_ERR = 9000
public void onCreate(Bundle savedInstanceState) {
gameActivity = this;
}
public static void buttonPressed() {
Log.e("pushNotification", "buttonPressed");
if (!mPlusClient.isConnected()) {
if (mConnectionResult == null) {
mConnectionProgressDialog.show();
}
try {
mConnectionResult.startResolutionForResult(gameActivity,REQUEST_CODE_RESOLVE_ERR);
} catch (SendIntentException e) {
mConnectionResult = null;
mPlusClient.connect();
}
}
}
The static method buttonPressed is called on my Menu Scene. It works well untill it crashes on the line with the code:
mConnectionResult.startResolutionForResult(gameActivity, REQUEST_CODE_RESOLVE_ERR);
as I posted, it is called on the "try" part.
Does any one can help me? What I am doing wrong? What parameter do I have to pass instead of "gameActivity"???
Many Thanks
run your buttonPressed() method on UI thread as follows:
Activity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
buttonPressed();
}
});
Try this

Categories