I am trying to handle the case where i need to refresh my view after an inapp language change has occurred
However, the method onConfigurationChange does not get called at all.
i put in my manifest the following flags:
android:configChanges="locale"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize|adjustPan"
public void onConfigurationChanged(android.content.res.Configuration newConfig) {
LogUtils.d("configuration has changed:%s",newConfig); => this line never runs
super.onConfigurationChanged(newConfig);
};
what do i do to make the onConfigurationChanged method run ?
Android has an Intent registered to this task, ACTION_LOCALE_CHANGED. So I believe you will have to have a BroadcastReceiver registered to listen this Intent filter and then do the necessary steps when you listen it. I am not sure about the entire code but here is a link which might help. http://android.codota.com/scenarios/518914fada0a610ad0c274da/android.content.IntentFilter?tag=out_2013_05_05_07_19_34
Related
I have very strange situation.
Having one app, I decided to create another one from the code of first one.
I copied .xml files, copied .java files so that everything is OK.
But there's one HUGE problem: my onNewIntent(Intent intent) method is called in first project, but it's not called in the second project (the code is the same!)
Method, which could trigger then, but can't trigger now
public void onClick(View arg0) {
Intent browserInt = new Intent (Intent.ACTION_VIEW,
Uri.parse("https://oauth.yandex.ru/authorize?response_type=token&client_id=zzzzz"));
browserInt.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(browserInt);
}
Here's onNewIntent() method:
#Override
protected void onNewIntent(Intent intent){
System.out.println(" I WORKED!");
Uri uri = intent.getData();
if (uri!=null) {
String m = uri.toString().split("#")[1];
String[] args = m.split("&");
String arg = args[0];
String token = arg.split("=")[1];
System.out.println(token);
}
}
I don't see "I WORKED" in my logs, unfortunately.
I've read lots of similar questions both on SO and over the Internet, tried setting Intent flags SINGLE_TOP, SINGLE_TASK and so on.
Here's the Android Manifest of WORKING project:
<application
android:name="yyy"
android:icon="#drawable/yaru_icon"
android:allowBackup="false"
android:label="xxx"
android:theme="#style/LightTheme">
<activity
android:name=".Main"
android:label="xxx"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
I'm quite desperate, why the similar code is not working anymore?
EDIT: I've tried everything: SINGLE_TOP, SINGLE_INSTANCE, SINGLE_TASK..
but then I occasionally did this on another activity:
Main m = new Main();
m.onNewIntent(this.getIntent());
And it finally worked!
I don't know, whether it's a dirty workaround or a bug, if anyone can explain it, please, comment.
PREAMBLE:
Allright, I'm a little late to this one, but as I stumbled over the same issue and no answer here or for any of the other four stackoverflow questions, I found for this issue, solved the problem for me, here's what I figured out.
ANSWER:
There are several possible reasons, why onNewIntent isn't called and I'm gonna list them all - well all of which I know.
As mentioned in many answers before and in the doc for the onNewIntent function (link in Yaroslavs answer), you either need the android:launchMode="singleTop" manifest entry for the activity, where you want onNewIntent to be called, or the Intent used for starting the activity must have the flag FLAG_ACTIVITY_SINGLE_TOP. You don't need both (it's a | aka. logical or not a & aka. logical and )! onNewIntent should also be called for android:launchMode="singleTask", but before you use that, you better check out the android:launchMode documentation, because it has much more consequences, than just one function call.
In older versions of Android there was a bug, which basically prevented android:launchMode="singleTop" from working as specified and thus onNewIntent from being called. The bug was never officially solved, but I couldn't reproduce it in version 4.4.2 (Samsung S4 Mini). So it seems to have been fixed at some point between 4.0.x and 4.4.2.
Not every time the preconditions as mentioned before are fulfilled, onNewIntent will be called. As the documentation of the function states:
...when the activity is re-launched while at the top of the activity stack instead of a new instance of the activity being started, onNewIntent() will be called on the existing instance with the Intent that was used to re-launch it."
That means, if the activity is newly created, onNewIntent won't be called, no matter what launchMode or Intent flags you did set!
To my understanding, either onCreate or onNewIntent is called, but never both.
So, if you wanna pass data to the activity through the Intent and it should always work (as in my case), no matter if the activity is relaunched or the activity is freshly created, you can do as described in this very useful blog post.
As a variation of the solution described in the above blog post, you could also take advantage of the fact, that no matter if onNewIntent or onCreate was called, onResume will always be called afterwards, and do something like this:
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
}
#Override
protected void onResume() {
super.onResume();
Intent intent = getIntent();
// ... do what you wanna do with the intent
}
For this example getIntent will always get you the Intent you used for the startActivity call or the Notification, as the new Intent will also be set for the Activity, if the Activity is freshly created (and thus onCreate was called).
POSTAMBLE:
Sorry for the long post. I hope you found something useful in it.
The Activity you want to receive onNewIntent() in should have
android:launchMode="singleTop"
Or add the flag tn intent
browserInt.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|
Intent.FLAG_ACTIVITY_SINGLE_TOP);
As documented in onNewIntent(Intent)
Here's one situation that might bite you, along with a bit more information: onNewIntent is called as expected with this code:
Intent intent = new Intent...
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
finish();
startActivity(intent);
but not with this code
Intent intent = new Intent...
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
finish();
The reason for that is that, in the second code block, the new activity is added on top before calling finish for the current activity, so to get the second code block to work you must add the FLAG_ACTIVITY_CLEAR_TOP flag as suggested by some of the other answers, like this:
Intent intent = new Intent...
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
Note that finish is not called at all here, because it is called for you. From the documentation for the FLAG_ACTIVITY_CLEAR_TOP flag:
If set, and the activity being launched is already running in the current task, then instead of launching a new instance of that activity, all of the other activities on top of it will be closed and this Intent will be delivered to the (now on top) old activity as a new Intent.
I was using onNewIntent for search implementation in Android. I came across the problem that onNewIntent wasn't being called when I used the Go button on the keyboard in the emulator. I solved the issue by placing my code for handling the intent in the onCreate method also. This needs to be done to make sure that the intent action is handled when a fresh instance of the activity is started.
This posed a problem as onCreate is called whenever the activity is restored from a previous state too. So, the intent handling method gets called even when an orientation change occurs.
Solution : Use if (savedInstanceState==null) to determine if activity is being restored from a previous state, or is it a fresh search.
The best way to handle onNewIntent with singleTop is simply this:
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
}
Then do all of your logic on getIntent inside onResume.
for me I didn't add search action to the activity in the manifest:
<activity android:name=".SearchResultsActivity" ... >
...
<intent-filter>
<action android:name="android.intent.action.SEARCH" />
</intent-filter>
...
</activity>
Check your steps here:
https://developer.android.com/training/search/setup
In my case, I just add launchMode="singleInstance" in the activity tag in the AndroidManifest file.
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleInstance">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Note: I was using kotlin.
To enter to the onNewIntent method, you need in your AndroidManifest.xml file, put after set you main activity a launch mode, in this launch mode you have to put singleInstance e.g:
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:launchMode="singleInstance"
android:windowSoftInputMode="adjustPan" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Now you will able to enter to you onNewIntent method.
I am having a strange problem in an Android application that I am building, the application is basically a Homescreen replacement app which will be put as a default homescreen in a device. To do some initialization work I have extended Android Application class and in the onCreate() method I am basically registering some observer and starting a service, here's the code:
public class MyApplication extends Application implements ExternalStorageListener {
private ExternalStorageObserver externalStorageObserver;
public void onCreate() {
Log.i("MyApplication", "Starting application");
super.onCreate();
externalStorageObserver = new ExternalStorageObserver(this);
if(externalStorageObserver.isExternalStorageAvailable()) {
// this builds a list of files present in the SD card
// which is being used through the application to do
// some work
buildData();
File externalFileDir = getApplicationContext().getExternalFilesDir(null);
if(externalFileDir != null && externalFileDir.isDirectory()) {
// do something...
}
}
//Register listener to observe external storage state
registerExternalStorageObserver();
Log.i("SyncService", "Starting sync service...");
ComponentName cmp = startService(new Intent(getApplicationContext(), SyncService.class));
Log.i("SyncService", cmp.toString());
}
private void registerExternalStorageObserver() {
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_MEDIA_MOUNTED);
filter.addAction(Intent.ACTION_MEDIA_REMOVED);
registerReceiver(externalStorageObserver, filter);
}
private void buildData() {
// builds a list
}
}
Content of Manifest file:
<application android:persistent="true" android:icon="#drawable/icon"
android:label="#string/app_name" android:name="com.webgyani.android.MyApplication"
android:debuggable="true">
<activity android:name=".HomeTabActivity" android:launchMode="singleInstance"
android:stateNotNeeded="true" android:theme="#style/LightTabsTheme"
android:screenOrientation="landscape" android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
This works fine when I install the app either using Eclipse or manually installing the apk onto the device. Once the app is installed things work fine, I mean the above onCreate() method gets called and service is also started normally, but if I reboot the device this time the onCreate() method does not get called(none of the log statements appear and also the services are not started). After some debugging I noticed that this only happens if I set my app as the default launcher/homescreen app and thereafter reboots the device, because once you set the app as the default launcher, Android should automatically launch your app as the homescreen after reboot. In my case the app is launched but that code is not executed.
I tried to use debugger but that didn't work because when I reboot the device the debugger gets disconnected and by the time USB debugging gets enabled my app is already started.
I even double checked the Logcat but didn't see any error. I thought of having a BOOT_COMPLETED intent to initialize that part, but that will require some code refactoring which I am not willing to do at this point of time unless there is a solution.
So I am curious to know that whether this is a standard behavior, or is there a known bug which causes this, because my assumption is the onCreate method of the Application will always get called whenever the app is started. I have tried whatever I could since morning, but nothing worked, couldn't pinpoint the issue, if any of you could shed some light into this then that would be highly appreciated.
Thanks
Well, finally I figured out the problem, and it was in my code itself. I initially suspected that the MyApplication's onCreate() method was not getting called, I had that assumption because I was not able to see any logs. To know whether the method is getting called or not, instead of using Log.i() I was also appending some additional log messages in an ArrayList and printing them later, this revealed that the methods were indeed getting called and even the Service was instantiating properly but the data or filelist is not being populated because the SDCard was not ready by that time. I am also pretty sure that the logs were not available on Logcat due to the fact that the USB debugger becomes ready after my app is started(as it's a homescreen app).
The actual problem becomes obvious when you see that my overridden MyApplication class implements a listener called ExternalStorageListener which basically extends BroadcastReceiver, I have created that class to receive SDCard related Intents for example ACTION_MEDIA_MOUNTED, ACTION_MEDIA_REMOVED to rebuild the data(file list). In my case the ExternalStorageListener class was not receiving the Intents because I forgot to add this filter.addDataScheme("file") in the registerExternalStorageObserver method above in the code sample.
I do agree that my question was based on a false assumption and the code example I posted it's kind of hard to figure out the actual issue. I am not sure what to do with the question whether to mark this as answer or leave it as it is.
hi
I have added an app to the Gallery share menu.
Selecting and sharing one image works fine and this code:
if (Intent.ACTION_SEND.equals(action)) {
in my onCreate is executed.
The problem is when i press back(destroy) and open the app again
The same Intent is received in the onCreate.
I use the :
android:launchMode="singleTop">
and the
protected void onNewIntent(Intent intent)
The onNewIntent is not firing.
I suspect i must clear out the Intent somehow.
and been trying to find and answer but im stuck
The problem is in your launchmode. It should be standard so each time it will initiate a new instance of activity.
As you are using a singleton so if you get back to your current activity again, it will not relaunched.
See this link for ref how launchmode works: http://developer.android.com/guide/topics/manifest/activity-element.html#lmode
found the solution so i answer my question for anyones delight
Added this to manifest:
<activity android:name=".ServicesDemo"
android:label="#string/app_name"
android:configChanges="keyboardHidden|orientation">
Added this to my ServicesDemo:
public void onConfigurationChanged(Configuration newConfig)
{
Toast.makeText(this, "onConfigurationChanged",Toast.LENGTH_LONG).show();
super.onConfigurationChanged(newConfig);
}
Orientation changes of the phone will trigger this method instead of onCreate
I have a simple question to solve, but I am not sure how to do it.
I have a class that extends Service that runs a thread looking for a TCP connection. If one comes in, it read an input message.
If the input message is "START", I start an activity, in this fashion:
Intent dialogIntent = new Intent(getBaseContext(), VoIPCall.class);
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
dialogIntent.putExtra("inetAddress", clientSocket.getInetAddress());
getApplication().startActivity(dialogIntent);
While this activity is running, the Service keeps running. At some point I may reserve a "STOP". I would like to call a method in the previously created Activity but I am not sure how to interact with it.
I do not want to use a static method. How can I please do that?
Thank you very much,
EDIT: I changed my code to this:
Intent dialogIntent = new Intent("com.voip.rudy.START_CALL");
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
dialogIntent.putExtra("inetAddress", clientSocket.getInetAddress());
getApplication().startActivity(dialogIntent);
And in the manifest:
<activity android:name=".VoIPCall">
<intent-filter>
<action android:name="com.voip.rudy.START_CALL" />
<action android:name="com.voip.rudy.STOP_CALL" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<category android:name="android.intent.category.DEFAULT" /> was required to avoid having it crash.
EDIT:
The solution given has fixed my issue but I wanted to actually act on member variables on that class, that are previously initialized. Say I call the constructor, then I would like to go back into this activity and act on the member variables.
The member variables are not initialized when I call one action after another, it seems to create a new activity somehow. Would there be anyway to act on the same activity, and keep the objects intact please?
James
Add the Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT flags to your intent and call startActivity with a new action or a special extra that can identify the intent.
In the activity, write a method called :
private void handleIntent(Intent intent) {
}
call this from onCreate (or onResume) using:
handleIntent(getIntent());
and also write:
#Override
protected void onNewIntent(Intent intent) {
setIntent(intent);
handleIntent(intent);
}
There are a few ways to do it, really depends on the overall structure of your application. All can work. Off the top of my head these are the methods that come to mind
1) Create a custom intent and have the activity or service react to it when the otehr sends it
2) Instead of the service, setup the logic looking for the tcp connection as an async task within the dialog activity, when you have the tcp connection you could pass it off to the service to do its work
3) Take a look at the local service and remote service SDK examples and use the callback code as the basis for passing data back to the activity. You can also call through the interface back to the service.
4) Maybe even setup a broadcast receiver 'architecture'. This has the advantage of decoupling the user activity from the service entirely. You could put some of your application logic in a service in another process, or even in a process that runs at device boot.
I think any of the techniques would work. I'm guessing that the behavior you are seeing is related to the lifecycle of the activities within android and you might need to move some of your processing to the onResume/onPause or onStart/onStop methods. If you you find that your activity onCreate is not being called, but you now your activity is active, it might jsut be that an activity instance from a previous invocation is still alive in the system. If so, it is possible that the OS is using that instead of the new activity that you want. The best way to see if this is a problem is to put some "Log.d" calls at the beginning and end of all of the activity methods that you override. You will be able to tell what is happening by watching logcat. The technique that you use may also be dependent on how synchronous you want the activity's reaction to be with the TCP event. If you want completely async you can go with a standard broadcast, or a service callback with a message send. If you want synchronous then do it with a service callback. In case you haven't seen it this SDK link has a pretty good description of the activity lifecycle http://developer.android.com/reference/android/app/Activity.html
I created a broadcast receiver in the main activity and the background service which is sending broadcast intents. The application crashes each time I try to run it and the Log displays the following error message:
10-04 13:30:43.218:
ERROR/AndroidRuntime(695):
java.lang.RuntimeException: Error
receiving broadcast Intent {
action=com.client.gaitlink.CommunicationService.action.LOGIN_STATUS_UPDATE
(has extras) } in
com.client.gaitlink.GaitLink$LoginStatusReceiver#431690e8
The broadcast message is sent from CommunicationService class in the following method:
private void announceLoginStatus(){
Intent intent = new Intent(LOGIN_STATUS_UPDATE);
intent.putExtra(SERVER_MESSAGE, mServerResponseMessage);
intent.putExtra(SESSION_STRING, mSessionString);
sendBroadcast(intent);
}
where
String LOGIN_STATUS_UPDATE = "com.client.gaitlink.CommunicationService.action.LOGIN_STATUS_UPDATE"
in the main activity the following broadcast reveiver is defined:
public class LoginStatusReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
String serverMessage = intent.getStringExtra(CommunicationService.SERVER_MESSAGE);
String sessionString = intent.getStringExtra(CommunicationService.SESSION_STRING);
userInfo.setSessionString(sessionString);
saveSettings();
}
}
and registered in onResume method:
IntentFilter loginStatusFilter;
loginStatusFilter = new IntentFilter(CommunicationService.LOGIN_STATUS_UPDATE);
loginStatusReceiver = new LoginStatusReceiver();
registerReceiver(loginStatusReceiver, loginStatusFilter);
And the manifest file includes the following:
<activity android:name=".GaitLink"
android:label="#string/app_name">
<intent-filter>
...
<action android:name="com.client.gaitlink.CommunicationService.action.LOGIN_STATUS_UPDATE" />
</intent-filter>
</activity>
I would really appreciate if anyone could explain why the Log displays the message above and the application crashes.
Thanks!
I solved it by adding intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); when you start a new activity.
If not started from an activity, intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); is needed.
You have two Intent filters; you only need one. If you register the BroadcastReceiver via registerReceiver(), only use the IntentFilter that is the second parameter to that API call -- do not also put an <intent-filter> element in the <activity> in the manifest.
I do not know for certain if that is your problem, but it certainly does not help.
Have you gone step by step in the debugger to find exactly where the crash occurs?
One thing to look out for is if you are overriding any Android lifecycle events that you are properly calling the base class's constructor when necessary.
when you are looking at error logs, you are just looking at first few lines.
but surprisingly actual problem is mentioned in lines way below it-
Fatal Error : Main
error receiving broadcast...bla bla bla <- you are just looking here only
at x.y.z.....
at x.y.z......
at x.y.z.....
at x.y.z......
caused by : ........................... <- but actual problem is here!
at x.y.z.....
at x.y.z......
at x.y.z.....
at x.y.z......
I'm not sure that you can understand what I want to say, because of my English.
I think this line of code is cause of a problem:
userInfo.setSessionString(sessionString);
My project was wrong because I want to:
int i = Integer.parseint(intent.getExtars("9"));
and you register two times.
i think you have to use life cycle method onPause() and onResume() Method for unregister and register broadcast intent.
I found that making sure the intent was run from the original activity and putting things into one class got rid of the entire issue.
This is a very old question, but I think many people would still be searching answers for it. My situation is quite similar to this one.
What I wanted to do, is to call finish() in the child activity when certain events occur in parent activity i.e. by sending the broadcast message from MainActivity to Child Activity.
Following is the code in MainActivity when the event is occurred (e.g. when network connection is broken etc etc):
Intent intent = new Intent("ACTIVITY_FINISH");
intent.putExtra("FinishMsg","ACTIVITY_FINISH: Network broken.");
sendBroadcast(intent);
In the child activity's OnResume() function:
IntentFilter quitFilter = new IntentFilter();
quitFilter.addAction("ACTIVITY_FINISH");
registerReceiver(m_quitReceiver, quitFilter);
In the child activity's OnPause() function:
unregisterReceiver(m_quitReceiver);
Within the child activity class:
BroadcastReceiver m_quitReceiver = new BroadcastReceiver()
{
public void onReceive(Context context, final Intent intent)
{
if (intent.getAction().equalsIgnoreCase("ACTIVITY_FINISH"))
{
Log.d("INFO", intent.getExtras().getString("FinishMsg"));
finish(); // do here whatever you want
}
}
};
Hope this helps.
It might because you keep registering BroadcastReceiver. I made that mistake before as a result it returns this error. Make sure BroadcastReceiver only registered once.
Ok what worked for me was declaring the onNotification method as follows:
window.onNotification = function(event) {
alert('onNotification called!');
};