widget only works after 2 installs or reboot - android

My widget application only works if I install the widget add it to the screen and then install it again, if i add another widget i have to install again in order for the second one to start working (rebooting the device also helps, after the reboot all the widgets on the screen work,
I have config file, and it does not reach my appWidgetProvider (the action is set on the onUpdate method), how can i force my APP to update the widget from the configuration file?
my entire project:
https://github.com/vlad1001/Widget
Thanks!

The only difference is see on your code is that your are finishing the activity before updating the widget.
From documentation, the onUpdate method will not be called the first time.
I think that your have to add the following:
super.onCreate(icicle);
setResult(RESULT_CANCELED);
Remove this line:
setResult(RESULT_CANCELED, resultValue);
After that, change the call to update before setResult and finish():
//make the update before finish()
appWidgetManager.updateAppWidget(appWidgetId, views);
Intent resultValue = new Intent();
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
setResult(RESULT_OK, resultValue);
finish();
I have not reproduce your issue, please let me know if this work for you.
After you share the source code, the base issue, is that on the first creation you are adding click intent to Text and on the update you add the pending intent to your imageView...
changing this line resolve your issue. Test on the PR...
views.setOnClickPendingIntent(R.id.example_widget_imageview, clickPendingIntent);

My first shot. Take a look at file AndroidManifest.xml in Your project.
There is a line which might cause problem You have described.
android:allowBackup="true"
Whether to allow the application to participate in the backup and restore infrastructure. If this attribute is set to false, no backup or restore of the application will ever be performed, even by a full-system backup that would otherwise cause all application data to be saved via adb. The default value of this attribute is true.
In short: uninstalling app doesn't mean You have uninstalled app's content and settings.
Try set it to false.
Related problem: https://stackoverflow.com/a/35296675/619673
Alternative: after first installation, clear cache of app, then run (or call in terminal adb shell pm clear <your.package.name).

Related

Some 3rd party widgets stop updating after application upgrade

My application hosts user installed widgets, same as a launcher application.
Once I bind the widget, everything works fine. Widgets are created, updated automatically, I can click to navigate inner views.
Everything keeps working fine, until I update my application from Play store (or manually with a signed APK).
After the update, the widgets still show but they won't update anymore. Some widgets function when I click on them but the view is stuck and never gets updated until I re-create the widget (get a new ID and bind it).
I tried forcing an update using
Intent intent = new Intent();
intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
intent.setComponent(appWidgetInfo.provider);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[]
{appWidgetId});
context.sendBroadcast(intent);
but that doesn't help...
I wanted to try a forced update on click but I couldn't find any way to get the widget's RemoteViews (as this is not my widget, I just host it).
RemoteViews views =
new RemoteViews(context.getPackageName(),R.layout.mywidget_layout);
Intent updateIntent = new Intent();
updateIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
updateIntent.putExtra(myWidgetProvider.WIDGET_IDS_KEY, ids);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
context, 0, updateIntent, PendingIntent.FLAG_UPDATE_CURRENT);
views.setOnClickPendingIntent(R.id.view_container, pendingIntent);
Also implemented an AppWidgetProvider to listen to widgets' ID changes (APPWIDGET_HOST_RESTORED) but it doesn't get called on my application update.
My next step would be to re-create all widgets after application update, but I really prefer not to do so.
Would appreciate any help!
Solved.
The last thing I wanted to do, was probably the first thing I should have tried.
I moved on to re-creating the widgets and I found that I don't have to fully re-create them, just re-call bindAppWidgetIdIfAllowed() with the same Widget ID I already have.
The method will return true if everything is still OK and if not, the widget may not be installed anymore or you need to trigger its configuration screen.
Certain Android functionality will break if the widget is installed on the SD Card. Try moving it to the device storage and re-test.
make sure you use unique keys with putExtra(MyWidgetProvider.WIDGET_ID_KEY, ids);
Do not use putExtra(AppWidgetManager.EXTRA_WIDGET_IDS, ids);

Exclude current activity from Recent Tasks

My app, running in background, at some point displays activity to purposefully interrupt user's flow. My activity starts a new task, which appears in "Recent Tasks" lists while being in foreground. Is there any way it could be prevented? Setting android:excludeFromRecents does not work - activity is not presented anymore in "Recent Tasks" only after is has been paused.
Manifest looks like:
<activity
android:name="com.example.recenttasks.MainActivity"
android:excludeFromRecents="true">
</activity>
and activity is started this way:
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
The key thing you mentioned is
appears in "Recent Tasks" lists while being in foreground
I think you can't change that behavior. I just tested on my app and the same thing happens. If I press the "recent tasks" button while having my activity in the foreground, it appears listed there. The moment I move out of it to another activity or to my phone's main screen, the activity is not listed anymore.
I also tested this on the built-in DeskClock app that comes with recent Android versions and the same behavior is present there when a new alarm is triggered. Note that the AlarmAlertFullscreen activity of that app has the same parameters you mentioned in your question.
I'm not sure you can circumvent this or why you would need to in the first place since the activity is not listed anymore once it loses the focus.
you are defined it in manifest that is enough but it is not coming..
ok..try add this flag also to your Intnet and start the Activity..
intnet.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
Should the user be able to return to it? (Meaning if it shows and user clicks recents, have they lost their chance to see the hidden activity or should it still be there?)
If they cannot return to it anyway then the best action would be to finish() the activity onPause(). This will mean that as long as you have used android:excludeFromRecents and android:noHistory="true", there will be no item in recents.
If however you do wish to return to the 'interruption' activity (but do not want a recents entry) you could consider still finishing the activity onPause - but also recording a preference flag (something like IS_INTERSTITIAL). Your other activities can then check this preference in onResume and, if it is true, send an Intent to restart the Interstitial instead - To the user it will just appear they are resuming the app in the same state as they left it (interstitial)
Edit: If the screen needs to stay (rather than be re-instantiated) it may be possible to use a DialogFragment, although then you must worry about configuration changes. There is one hack you could try (explained in this answer) -
Set your label empty By using android:label="" your recent task is excluded. however this is a definite hack which may produce inconsistent results (as I haven't tested it to be sure)

Android package installer - how to get "Open" and "Done" and activity result both?

My Android Application has an option to upgrade to the newer version, the newer version APK I keep it available under a path in sdcard. On click of Upgrade option I invoke following method.
public static void launchInstaller(Activity act, String apkPath)
{
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(apkPath)), "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
act.startActivityForResult(intent, 0);
}
The reason I include FLAG_ACTIVITY_NEW_TASK, is because, after upgradation, I want to have "Open" & "Done" options, which aren't shown if I don't use this flag.
When the above code launches the package installer, it has two options OK & Cancel, when user press Cancel, I want to know user cancelled it. But I am unable to know because the onActivityResult is called pre-maturely. I come to a reason why is that happening after reading the following posts.
Android - startActivityForResult immediately triggering onActivityResult
onActivityResult() called prematurely
They ask me to make sure that the Intent I am using to launch the activity doesn't have FLAG_ACTIVITY_NEW_TASK set on it. See here:
http://developer.android.com/reference/android/content/Intent.html#FLAG_ACTIVITY_NEW_TASK
In particular note: "This flag can not be used when the caller is
requesting a result from the activity being launched."
If the activity is being launched as part of a new task then Android
will immediately call the onActivityResult() with RESULT_CANCELED
because an activity in one task can't return results to another task,
only activities in the same task can do so.
But in my case, I can't remove FLAG_ACTIVITY_NEW_TASK, because otherwise I will not get "Open" and "Done" options on successful upgradation.
Has anybody faced similar sort of problem? Kindly help me out, as it drives me nuts.
You should use package added broadcast intent. Create a broadcast receiver listen package added.
If added package equals your package, user confirm install otherwise dismiss install process. If you ask what kind extras can be return by android, android returns EXTRA_UID about package. PackageManager' s method convert uid to package.(getPackagesForUid(int uid) returns String array but it usualy return one item in the array in short usually array length equals 1.

Create new intent in background

I am looking for a way to launch another app from within my app but so that the focus is not changed from my app to the app launched.
I.e currently I have the new app launched via a intent, however when this is carried out the new app is launched and becomes the app in view, I need it to be kept in the background with my app still in view.
The reason for this?
I am developing an application for internal use that will act like a lock-screen to the device so although things must happen in the background the 'lock-screen' must always be on top.
I have done some research into intents and launching other apps but can not find anything about what I need.
Hope you can help thank you!
Currently the terminal is called like this:
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setComponent(new ComponentName("jackpal.androidterm", "jackpal.androidterm.RemoteInterface"));
intent.setAction("jackpal.androidterm.RUN_SCRIPT");
intent.putExtra("jackpal.androidterm.iInitialCommand", cmdString);
The reason it needs to be running in the background is so that the app can run commands in terminal without the user having access, but then they 'unlock' the screen they need to then be able to view the terminal and what commands are being run etc
You can not startActivity in Background.Instead start the activity and minimise the activity(in your case this activity is of different application) using moveTaskToBack(true);
In your case, put a condition based on your intent and its params and use moveTaskToBack(true); so that activity will be minimised only when your application launches.
This won't be possible, you will have to start a background Service that does the actual work and only launch the Activity you want to navigate to once your foreground Activity is finished. Depending on your architecture, you can store the Activity to call when your foreground Activity is finished and change it from the service. That way you will have your desire behaviour without having to actually call the Activity.
In addition to the answer from #Meher, in the intent for your current starting activity, you can add the flag FLAG_FROM_BACKGROUND.
With this you get rid of the "blinking" effect (the one where your activity shows for one fraction of second while it discovers wether to go to background)

Android AppWidget Configuration - Start in new task

I've searched and searched and searched for this!
So I've got an app widget and it has a configuration activity that I can open when pressing a button on the app. The scenario is:
Had the app opened.
Closed the app with the home button.
Selected to add my widget
I have configured the widget.
Placed on my home screen
Then open the configuration activity again with the button on the widget.
Cancel the new config by pressing back will put me back into the app.
When pressing back I want to just return home.
Basically what I'm asking is. How do I start the configuration activity in it's own task/stack?
I've looked into intent filters but I'm just not quite sure, or maybe it's something to do with the package it's in, or maybe it's just not possible!
I suppose it may have something to do with the intent I use to launch the config activity
Intent configIntent = new Intent(this, Configuration.class);
configIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
remoteView.setOnClickPendingIntent(R.id.config, PendingIntent.getActivity(this, 0, configIntent, PendingIntent.FLAG_UPDATE_CURRENT));
Perhaps because I launch it with 'this' as the context, it will always start in my applications stack...
but the pending intent api is:
PendingIntent API 1
"Note that the activity will be started outside of the context of an existing activity"
So yeah I'll stop talking now as I just end up going in circles!
EDIT
So tried android:launchMode="singleInstance" in the manifest like was stated. This worked however it stops the 'startActivityForResult' behaviour working correctly. (which is the whole reason for a config activity) Get the error:
WARN/ActivityManager(59): Activity is launching as a new task, so cancelling activity result.
So still haven't found a solution.
Ok sorted it :-) needed:
android:taskAffinity=""
in the manifest, setting the task affinity to an empty string allows for the activity to start in it's own stack, as it is not 'affiliated' with the rest of the application.
UPDATE
I have changed the task affinity to:
android:taskAffinity="com.my.package.alternative.task"
as each time I launched the activity it was showing up multiple times in the 'history'. So it now starts in it's own stack but is shared with other instances of the same activity.
Also need to add the Flag Intent.FLAG_ACTIVITY_NO_HISTORY to your intent :-) this stops your getting your application multiple time's in the history when you 'press and hold' the home button.
UPDATE
I've noticed FLAG_ACTIVITY_NO_HISTORY wasn't doing what I wanted, I've removed it and added:
android:excludeFromRecents="true"
into the activity tag in the manifest as well. The activity now behaves like I want :-)
Got this answer from the following link trail:
Tasks & Back Stack |
Managing Tasks |
Affiliation Tag
Try to put android:launchMode="singleInstance" for an activity of the app in AndroidManifest.xml

Categories

Resources