I have a fragment HostEditFragment which is loaded up by activity HostEditActivity. When I finish editing in the fragment I'd like to call a method on MainActivity. I'm trying to do it with an Interface and intent at the moment but it starts a new MainActivity and doesn't seem to work.
Just wondering if there's a better way of doing this.
I think it's creating a new MainActivity rather than using the existing one as SfnViewerFragment is coming back as null. I need it to be the existing MainActivity and SfnViewerFragment.
Here's some skeletal code so you can see what I've tried.
HostEditFragment:
public class HostEditFragment extends Fragment {
OnViewerEditedListener callback;
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
callback = (OnViewerEditedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnViewerEditedListener");
}
}
public void saveHost() {
//...
callback.onViewerEdited(id);
}
public interface OnViewerEditedListener {
public void onViewerEdited(Long id);
}
}
HostEditActivity:
public class HostEditActivity extends ActionBarActivity implements HostEditFragment.OnViewerEditedListener {
public void onViewerEdited(Long id) {
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("id", id);
startActivity(intent);
}
}
MainActivity:
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Uri data = getIntent().getData();
Uri viewerUri;
if (data != null) {
//....
} else {
Long id = getIntent().getLongExtra("id", -1);
if (id != -1) {
onViewerEdited(id);
}
}
public void onViewerEdited(Long id) {
SfnViewerFragment sfnViewerFragment = (SfnViewerFragment) getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.pager + ":0");
sfnViewerFragment.recreateWebView(id);
viewPager.setCurrentItem(0, true);
}
}
Related
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.
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
I have created an application in which when I turn on bluetooth a toast is shown and a new activity starts. This is my broadcast receiver class:
public class BroadCast extends BroadcastReceiver {
String prefs="myPrefs";
String count="myCount";
static int counter=0;
Intent i;
#Override
public void onReceive(Context arg0, Intent arg1) {
String bluth = arg1.getAction();
if (bluth.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
if(arg1.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1) == BluetoothAdapter.STATE_ON){
SharedPreferences sp = arg0.getSharedPreferences(prefs, Context.MODE_PRIVATE);
Editor ed = sp.edit();
ed.putInt(count, counter);
ed.commit();
counter++;
Toast.makeText(arg0, "Bluetooth on " + sp.getInt(count, 0), Toast.LENGTH_LONG).show();
i = new Intent(arg0, Indicators.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
arg0.startActivity(i);
Indicators.on.setVisibility(View.VISIBLE);
} else if (arg1.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1) == BluetoothAdapter.STATE_OFF) {
} else if (arg1.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1) == BluetoothAdapter.STATE_TURNING_OFF) {
} else if (arg1.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1) == BluetoothAdapter.STATE_TURNING_ON) {
}
}
}
}
Now there is no problem. The activity is starting but in the above code when I put
Indicators.on.setVisibility(View.VISIBLE);
And run the app, It crashes!
Actually on is a textview obj which I have defined in Indicators class as follows:
public class Indicators extends Activity {
static TextView on, off, opening, closing;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.textviewbluetooth);
opening = (TextView)findViewById(R.id.textView1);
on = (TextView)findViewById(R.id.textView2);
closing = (TextView)findViewById(R.id.textView3);
off = (TextView)findViewById(R.id.textView4);
opening.setVisibility(View.INVISIBLE);
on.setVisibility(View.INVISIBLE);
off.setVisibility(View.INVISIBLE);
closing.setVisibility(View.INVISIBLE);
}
}
How should I remove this error?
class YourActivity extends xxxx {
private static YourActivity mInst;
public static YOurActivity instance() {
return mInst;
}
/// Do your task here.
public void setViewText(xxxx) ;
#Override
public void onStart() {
...
mInst = this;
}
#Override
public void onStop() {
...
mInst = null;
}
}
And in your BroadcastReceiver:
YOurActivity inst = YOurActivity.instance();
if(inst != null) { // your activity can be seen, and you can update it's context
inst.setViewText...
}
Put this line
on.setVisibility(View.VISIBLE);
Inside the Activity -> onCreate() method.
Do not use static references to the Activity class members like TextViews from outside the Activity itself as it might have been destroyed, or not have been created yet. This is bad practice in general.
Edit: Add an extra to the Activity starter intent if you need a flag to show the indicator.
I have a subclass checkLoginTask in my Activity LoginActivity (this activity is for the login of a user) . This subclass is called from in the onPostExecute() from a class that extends AsynTask.
I want to destroy the activity LoginActivty if theLoginOk == "ok" and start the activity MainActivity. I used finish() but I got a error Non-Static method "finish()" cannot be referenced from a static context
I tried with final Activity activity = this; but does not worked.
this is the method on my Avtivity LoingPage
public static void checkLoginTrue(JSONObject jsonObject, Context context){
if(jsonObject != null) {
Intent intent = new Intent(context, MainActivity.class);
try {
JSONObject student = jsonObject.getJSONObject("status");
String theId = student.getString("id");
String theLoginOk = student.getString("login");
Log.i("JSON login", theLoginOk);
if (theLoginOk.equals("ok")) {
intent.putExtra("id", theId);
intent.putExtra("login", theLoginOk);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
} else {
// something
}
} catch (JSONException e) {
Log.w("error", e.getMessage());
}
}
}
How can I solve this?
here no need for static method. if you want practice for calling static method in activity class, Create onr Util class in that create static methods and call from activity override methods.
like
public class Utill
{
public static void checkLoginTrue(JSONObject jsonObject, Context context, Class<? extends Activity> myClass){
if(jsonObject != null) {
Intent intent = new Intent(context, myClass);
try {
JSONObject student = jsonObject.getJSONObject("status");
String theId = student.getString("id");
String theLoginOk = student.getString("login");
Log.i("JSON login", theLoginOk);
if (theLoginOk.equals("ok")) {
intent.putExtra("id", theId);
intent.putExtra("login", theLoginOk);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
} else {
// something
}
} catch (JSONException e) {
Log.w("error", e.getMessage());
}
}
}
}
then call
Utils.checkLoginTrue(jsonObject, this, MainActivity.class);
in your activity any override non-static and/or static method.
Use Broadcast receiver to finish activity or eventbus to avoid leaks in memory, singletons should not exists in android!
Example:
public class FinishableActivity extends AppCompatActivity {
public static final String ACTION_FINISH = FinishableActivity.class.getName() + ".FINISH";
public static final String EXTRA_ACTIVITY_CLASS = "EXTRA_ACTIVITY_CLASS";
private FinishBroadcastListener finishReceiver;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
finishReceiver = new FinishBroadcastListener()
.register(this);
}
#Override
protected void onDestroy() {
finishReceiver.unregister(this);
finishReceiver = null;
super.onDestroy();
}
public static void show(Context context, Class<? extends Activity> cls) {
context.startActivity(new Intent(context, cls) {{
addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_REORDER_TO_FRONT | FLAG_ACTIVITY_BROUGHT_TO_FRONT);
}});
}
public static void hide(Context context, Class<? extends Activity> cls) {
context.sendBroadcast(new Intent(ACTION_FINISH) {{
putExtra(EXTRA_ACTIVITY_CLASS, cls);
}});
}
class FinishBroadcastListener extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String action = (intent == null) ? "" : intent.getAction();
action = (action == null) ? "" : action;
if (ACTION_FINISH.contentEquals(action)) {
onFinishCalled((Class<? extends Activity>) intent.getSerializableExtra(EXTRA_ACTIVITY_CLASS));
}
}
public FinishBroadcastListener register(Context context) {
context.registerReceiver(this, new IntentFilter(ACTION_FINISH));
return this;
}
public void unregister(Context context) {
context.unregisterReceiver(this);
}
}
private void onFinishCalled(Class<? extends Activity> cls) {
if (cls == null) {
return;
} else {
if (cls.equals(getClass())) {
finish();
}
}
}
}
Your finish() didn't work when you tried because you need an actual activity object to call it on. Static methods do not run on objects. Thats why they can't use this.
You must pass your activity object reference to the static method and then finish() it. If you have already passed it as Context context then cast it to activity first. Example:
//if your context is actually activity reference, use line below
//if not, add another Activity argument to the method
//if you cant get to the activity to pass it as argument, save it in a static reference somewhere, during ocCreate for example, and you can access it globally
Activity activity = (Activity) context;
//correct way to use finish()
activity.finish();
I have 2 classes which are GcmMessageHandler and Control (its an activity class, shows some graphics). When i handle the gcm message, i want to refresh control class (but if its front)
public class GcmMessageHandler extends IntentService {
String mes;
private Handler handler;
public GcmMessageHandler() {
super("GcmMessageHandler");
}
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
handler = new Handler();
}
#Override
protected void onHandleIntent(Intent intent) {
Bundle extras = intent.getExtras();
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
// The getMessageType() intent parameter must be the intent you received
// in your BroadcastReceiver.
String messageType = gcm.getMessageType(intent);
mes = extras.getString("title");
showToast();
Log.i("GCM", "Received : (" +messageType+") "+extras.getString("title"));
GcmBroadcastReceiver.completeWakefulIntent(intent);
}
public void showToast(){
handler.post(new Runnable() {
public void run() {
if(mes.equals("Control")){
}else{
Toast.makeText(getApplicationContext(),mes , Toast.LENGTH_LONG).show();
}
}
});
}
}
In this part:
if(mes.equals("Control")){ }
if the control activity class is resume, i want to refresh it. How can i do this?
You can use a BroadcastReceiver in order to notify your activity about any changes. So register a BroadcastReceiver in your activity first:
public class MainActivity extends Activity {
public static String REFRESH_ACTIVITY = "com.domain.action.REFRESH_UI"
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// do UI updates
}
};
#Override
public void onResume() {
super.onResume();
// do UI updates
IntentFilter filter = new IntentFilter();
filter.addAction(REFRESH_ACTIVITY);
this.registerReceiver(broadcastReceiver, filter);
}
#Override
public void onPause() {
super.onPause();
this.unregisterReceiver(broadcastReceiver);
}
...
}
Then send the broadcast to perform the UI update from any location:
if (mes.equals("Control")) {
Intent intent = new Intent();
intent.setAction(MainActivity.REFRESH_ACTIVITY);
sendBroadcast(intent);
}
Maybe you could use an observer design pattern.
Let the GcmMessageHandler hold the Control activity as an observer and then notify it when needed.
public class GcmMessageHandler extends IntentService {
String mes;
private Handler handler;
private Control mObserver
public GcmMessageHandler() {
super("GcmMessageHandler");
}
public void attachObserver(Control ctrl) {
mObserver = ctrl;
}
Then you just add a method to the Control class that can be called from the GcmMessageHandler class.
if(mes.equals("Control")){
mObserver.update(); // example
}else ...
It would be more slick if you first defined an observer interface:
public interface IObserver {
public abstract void update();
}
and had your Control class implement that. This way your GcmMessageHandler class could have a list of observers:
public class GcmMessageHandler extends IntentService {
String mes;
private Handler handler;
private List<IObserver> mObservers;
public GcmMessageHandler() {
super("GcmMessageHandler");
}
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
handler = new Handler();
mObservers = new ArrayList<IObserver>();
}
public void attachObserver(Control ctrl) {
mObservers.add(ctrl);
}
private void notify() {
for(IObserver observer : mObservers)
observer.update();
}
And of course if the Control class is the one holding the GcmMessageHandler object your just call the attach method from Control like this:
myGcmMessageHandler.attachObserver(this);