I have two activities SplashScreen and MainActivity.
MainActvity download some data and show it.
Now I want to start both activities on application start, MainActivity in background and SplashScreen in foreground and when the data of MainActivity download complete I want to make MainActivity foreground and finish SplashScreen.
I have seen many solution but no one is going good in my situation.
Please give me some suggestion or example .
I think it's better to make splash screen to download data and when it completed show new activity (MainActivity). In onStart metod use downloaded data stored on phone.
Your example: The only way You can have resolve this your way is by start MainActivity first and from onStart start SplashScreen:
class SplashScreen extends Activitiy {
public void onStart() {
EventBus.register(this);
}
#Subscribe
public void finishedDownload(FinishedDownloadEvent) {
this.finish()
}
}
class MainActivity extens Activity () {
public void onStart () {
open(new Intent(SplashScreen.class)); // We would like to have
download();
}
public void download (OnFinish onFinish) {
... download
EventBus.post(new FinishedDownloadEvent());
}
}
I forgot:
class EventBus {
private final static Bus instance = new Bus();
public static void register (Object obj) {
instance.register(obj)
}
public static void post (Event obj) {
instance.post(obj)
}
}
EventBuss
Related
I think this question may simple but I didn't find any solution for this,
I there any way in Android that if any one of an activity calls onPause() I need to show Toast message or any notification kind of thing need to show. Generally I want to get notified when activity calls onPause() but I need it in one place since I may have some 15 activity I don't want to add it in all the activity.
ex:If I have activity when any one of the activity calls onPause I need to get notified but that notification code should be in one place and we should not add any line of code onPause() Is it possible to do this.
Thanks.
Create a baseActivity, which has for example :
open class BaseActivity : AppCompatActivity() {
override fun onPause() {
super.onPause()
Toast.makeText(this, "notified", Toast.LENGTH_SHORT).show()
}
}
Then you can extends this in your activities and handle the on pause call in BaseActivity
If your minSdkVersion >= 14, you can use Application.ActivityLifecycleCallbacks: ActivityLifecycleCallbacks
You have to define a custom Application class and you can register for this callbacks afterwards:
public class MyApplication extends Application {
private class LifecycleCallbacks implements Application.ActivityLifecycleCallbacks {
#Override
public void onActivityCreated(final Activity activity, final Bundle savedInstanceState) {
//nothing to do
}
#Override
public void onActivityDestroyed(final Activity activity) {
//nothing to do
}
#Override
public void onActivityPaused(final Activity activity) {
// TODO Do your stuff, e.g. show toast.
}
#Override
public void onActivityResumed(final Activity activity) {
//nothing to do
}
#Override
public void onActivitySaveInstanceState(final Activity activity, final Bundle outState) {
//nothing to do
}
#Override
public void onActivityStarted(final Activity activity) {
}
#Override
public void onActivityStopped(final Activity activity) {
}
}
private final LifecycleCallbacks callbacks;
public void onCreate() {
super.onCreate();
callbacks = new LifecycleCallbacks();
application.registerActivityLifecycleCallbacks(callbacks);
}
}
Create a BaseActivity which contain all the methods you want to use in all other activities.
Then extend every activity with BaseActivity to call onPause() method.
Just to make it clear, this is not I want. I want to access another Activity's context.
Suppose I've two activities, MainActivity and WebActivity. In MainActivity I used oAuth2 login, and after login I start the WebActivity. In WebActivity I need to logout with the function mTencent.logout(MainActivity.this);, the question is how can I access MainActivity from WebActivity?
If I do this directly, I get the error,
MainActivity is not an enclosing class?
Considering I'm a starter of android, here may be not the exact way to implement it.
Will someone help? Thank you!
The API : void com.tencent.tauth.Tencent.logout(Context context)
Use Application context in your login and logout methods. As they will be managed at Application level.
So change mTencent.logout(MainActivity.this); to mTencent.logout(getApplicationContext());.
Also change your login method to work in application context.
Instead of using context of one activity in other which may result in crashes sometimes.
u can use libraries like EventBus to link the code.
Define a class which implements event u want to perform eg:LogOutEvent.java
public static class LogOutEvent { /* Additional fields if needed */ }
U can post events like logout from WebViewActivity.java using following command
EventBus.getDefault().post(new LogOutEvent());
and in MainActivity you first need to register event bus
#Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
#Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
and then in MainActivity you can subscribe for events like this
#Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(LogOutEvent event) {/* Do log out here */};
There is a good practice solution to your problem which involves certain steps to be performed:
1- Define an interface:
public interface LogOutInterface {
public void logout();
}
2- Have your MainActivity implement this interface:
public class MainActivity extends ???? implements LogOutInterface {
...
#Override
public void logout(){
//your logout procedure
}
}
3- Have a public method for your WebActivity and allow it to accept LogOutInterface:
public class WebActivity ... {
private LogOutInterface logoutInterface;
...
public void setLogOut(LogOutInterface logoutInterface) {
this.logoutInterface = logoutInterface;
}
}
4- call setLogOut from MainActivity:
public class MainActivity ... {
public void yourmethod() {
...
webActivity.setLogOut(this);
}
}
5- call logout function from your WebActivity:
public class WebActivity ... {
...
public void yourmethod() {
logoutInterface.logout();
}
}
hope this helps.
This is a workable one.
In the MainActivity, public static Activity thisActivity; & thisActivity = this; then in the WebActivity mTencent.logout(MainActivity.thisActivity);
or just can put the logout function as public static function of MainActivity,
public static void logout() {
if (mTencent.isSessionValid()) {
mTencent.logout(thisActivity);
}
}
then call MainActivity.logout() from WebActivity.
1. Javascript file ------ calls -------> CORDOVA PLUGIN(plugin.java)
2. CORDOVA PLUGIN(plugin.java) file -------calls-------> Android BroadcastReceiver file(Broadcast_Receiver.java)
Broadcast_Receiver.java contains onResume.
How do I call/initiate it from Javascript file?
Please see sample code at the bottom
Problem #1: I can't combine plugin.java & Broadcast_Receiver.java because they are extending CordovaPlugin & WLDroidGap respectively.
Problem #2: When I navigate between pages of my worklight application; onResume of Broadcast_Receiver.java never gets triggered because onResume is in native Android code
Possible solution which i was unable to implement:
use cordova onResume i.e.: document.addEventListener("resume", function() { });
merge plugin.java & Broadcast_Receiver.java
In short: how to initiate android lifecycle using a Cordova plug-in?
Sample code
Javascript file calls plugin
//some code
currentPage.myfunction= function() {
cordova.exec(Success, Failure, "plugin","someMETHOD", []);
}
plugin.java
public class plugin extends CordovaPlugin
{
//some code
float value= Broadcast_Receiver.Variable_Name;
//some code
}
Broadcast_Receiver.java
public class roamingadvisor extends WLDroidGap {
//some code
onCreate(){}
onResume(){}
onPause(){}
//some code
}
What I am trying to achieve
My application starts calculating data usage once it receives broadcast that data got activated
I am able to calculate data usage
It gets updated once i press home button & relaunch my app(i.e. trigger native onResume in android)
But when i keep using my application (i.e navigate between UI screen) native android onResume never gets triggered
Or
should i do it using entirely different approach?
*******R&D *******
I used below two link
https://apache.googlesource.com/cordova-android/+/2.6.x/framework/src/org/apache/cordova/Device.java
https://github.com/apache/cordova-android/blob/master/framework/src/org/apache/cordova/CordovaPlugin.java
and wrote follwing code for my need
public class Myclass extends CordovaPlugin {
IntentFilter intentFilter = new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE");
boolean multitasking=true;
BroadcastReceiver mReceiver=null;
//constructor
public MyDataUsage(){
}
public void initialize(CordovaInterface cordova, CordovaWebView webView) {
super.initialize(cordova, webView);
//Device.uuid = getUuid();
this.initReceiver();
}
#Override
public void onPause(boolean multitasking) {
super.onPause(multitasking);
this.cordova.getActivity().unregisterReceiver(this.mReceiver);
}
#Override
public void onResume(boolean multitasking) {
super.onResume(multitasking);
this.cordova.getActivity().registerReceiver(this.mReceiver, intentFilter);
}
public void onDestroy() {
this.cordova.getActivity().unregisterReceiver(this.mReceiver);
}
private void initReceiver() {
this.mReceiver=new BroadcastReceiver(){
#Override
public void onReceive(Context context, Intent intent) {
ctb=context;
if (intent.getAction().equals("android.net.conn.CONNECTIVITY_CHANGE"))
{
//My code
}
}
}
};
this.cordova.getActivity().registerReceiver(this.mReceiver, intentFilter);
}
public boolean execute(String action, JSONArray arr,
final CallbackContext callbackcontext) throws JSONException {
if (action.equals("getDataUsage")) {
try {
//code
callbackcontext.success(""+dataUsed+ ":" +timeElapsed+":"+StartTime);
} catch (Exception e) {
callbackcontext.error("ERROR :");
}
return true;
}
return false;
}
}
But onPause & onResume still gets called only when i press HOME key & RELAUNCH my APP
Should i CONCLUDE that " I can not implement ACTIVITY LIFECYCLE while naviagting in my UI/html SCREEN/pages" ???
By default Cordova application consist of a single Activity which hosts a single WebView. When you're navigating pages/changing content in web you will not get any lifecycle events from Activity because technically you're still in a context of a same Activity.
Note that CordovaPlugin class has callbacks for many Activity lifecycle methods, you can leverage them (https://github.com/apache/cordova-android/blob/master/framework/src/org/apache/cordova/CordovaPlugin.java). For example use initialize() method for starting your calculation and onDestroy() method to detect when your app is being closed. You can also use other CordovaPlugin methods such as onResume() and onPause() according to the logic you're trying to implement.
I just recently started learning how to build android apps, and encountered a problem:
I want, when users leave the app (go to the homescreen, multitask), and they return, that the app calls a certain method. How can I do that?
This problem is more tricky than it may look like. When you return to app after leaving it, then is called method onResume of activity which was active when app was interrupted. But same happens when you go from one activity to another (onResume of second activity is called). If you just call method from onResume, it will be called every time onResume of any activity is called.
Take a look at this solution...
First, you have BaseActivity which is extended by all activities that need to call that method:
abstract public class BaseActivity extends Activity implements IName {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
protected void onResume() {
if (AppClass.getPausedActivity() != null) {
if (this.getClassName().equals(AppClass.getPausedActivity()))
//call specific method
}
AppClass.setPausedActivity("");
super.onResume();
}
#Override
protected void onPause() {
AppClass.setPausedActivity(this.getClassName());
super.onPause();
}
#Override
abstract public String getClassName();
}
As you can see it implements interface IName:
public interface IName
{
String getClassName();
}
BaseActivity in onPause (when it is interrupted) calls setPausedActivity method of AppClass which remembers last activity name that was interrupted. In onResume (when app and activity is continued) we compare name of current activity and last paused activity.
So, when app is interrupted, these names will be same because you paused one activity and you got back to the same one. When you call activity from some other activity these names will not be same and method will not be called.
Here is code for AppClass:
public class AppClass extends Application {
public static String pausedActivity;
public static String getPausedActivity() {
return pausedActivity;
}
public static void setPausedActivity(String _pausedActivity) {
pausedActivity = _pausedActivity;
}
}
Also, here is example of activity that extends BaseActivity:
public class MainActivity extends BaseActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
}
//here you set name of current activity
#Override
public String getClassName() {
return "MainActivity";
}
}
You are bound to the Activity lifecycle. You will need to implement corresponding logic to figure out if the user has been in your app before (i.e. using SharedPreferences).
I have several activities which use several audio features. For that, I have a MediaPlayer in a singleton java class, so the activities interact with that class and just exist on the media player.
One of the features is to stop automatically the media player after X minutes. So I created a timer in the singleton class and stops perfectly the radio streaming. the problem is that there is no feedback or callback to the running activity. There is a play/stop button wich has to change the image and I do not know how can I capture that onStop event or whatever....or can be called from a single java class the current activity class running, so I could call a function of the activity in order to change the image?
You probably want to use a broadcast receiver for this.
From your singlton class which does the stopping, when your timer stops the music, call this method:
public void broadcastMusicPaused(View v){
Intent broadcast = new Intent();
broadcast.setAction("MUSIC_STOPPED");
sendBroadcast(broadcast);
}
Then, from your controlling activity, set up your receiver like this:
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(), "Music Paused", Toast.LENGTH_SHORT).show();
displayMusicStopped(); //switches images
}
};
#Override
protected void onResume() {
IntentFilter filter = new IntentFilter();
filter.addAction("MUSIC_STOPPED");
registerReceiver(receiver, filter);
super.onResume();
}
#Override
protected void onPause() {
unregisterReceiver(receiver);
super.onPause();
}
First of all, thanks jameo for his answer, sounds pretty good, but i do not know if i will have time to try, i promise i will if i can this week or next time i have a similar issue.
Finally i did the trick this way:
1 - Create a Interface with Method onStopMediaPlayer(); //For example call MediaPlayerStopInterface
public interface MediaPlayerStopInterface {
/**
* Called when the player timer ends
*/
public void onStopMediaPlayer();
}
2 - My activities classes implements the interface switching images.
public class PortadaActivity extends Activity implements MediaPlayerStopInterface{
public void onStopMediaPlayer(){
//Switch images or whatever
}
}
3 - My singletton class has an object of the type of the interface MediaPlayerStopInterface
public class AudioControllerClass { //The Singletton Java Class
private MediaPlayerStopInterface currentActivity;
public void setCurrentActivity(MediaPlayerStopInterface mpsi){
currentActivity=mpsi;
}
}
4 - My activities classes in onResume() do a Singlettonclass.setStoppedPlayerInterface(this), so i always have a reference of the running activitie.
public class PortadaActivity extends Activity implements MediaPlayerStopInterface{
public void onResume() {
AudioControllerClass.getInstance(getApplicationContext()).setCurrentActivity(this); //In every resume the singletton class knows who was the last one in being active
}
}
5 - when timer execute, as i have the activitie class reference, i just call object_StoppedPlayerInterface.stoppedPlayer();
public class AudioControllerClass { //The Singletton Java Class
class TimerRadio extends TimerTask {
public void run() {
if(whatever==true){
currentActivity.onStopMediaPlayer();
}
}
}
}
Finally, i didn't code it, but the callback to onStopMediaplayer in activities must be done with a Handler, if you do not want a "Only UI thread can touch his views" exception :P
It works perfectly :). But i don't know if it is a really bad practice or is not so horrible xD
Anyway thanks Jameo. Yours sound much more elegant :P