Binding Widgets in Custom Launcher - android

I'm having some issues adding widgets to the homescreen in a custom Launcher I've been working on.
I've been able to generate a list of widgets to add with an AppWidgetManager and I've developed the workflow for adding the widget to my home screen. The code is not quite what is below but looks something like the following:
AppWidgetHost widget_host = new AppWidgetHost(this, 1);
AppWidgetManager widget_manager = AppWidgetManager.getInstance(this);
int widget_id = widget_host.allocateAppWidgetId();
AppWidgetProviderInfo widget_provider = ... //from an array;
Intent bindIntent = new Intent(AppWidgetManager.ACTION_APPWIDGET_BIND);
bindIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widget_id);
bindIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER, widget_provider.provider);
startActivityForResult(bindIntent, REQUEST_BIND_APPWIDGET);
if (widget_provider.configure != null) {
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
intent.setComponent(widget_provider.configure);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widget_id);
startActivityForResult(intent, REQUEST_CREATE_APPWIDGET);
} else {
createWidget(widget_id);
}
I then have an onActivityResult method that leads to the configuration of widgets if necessary, and the createWidget method uses the createView method of the AppWidgetHost.
This workflow works but the ACTION_APPWIDGET_BIND intent asks the user for permission to bind the app, which is kind of annoying. My understanding is that only system apps can request this permission and that I am out of luck in binding widgets without asking for this permission while the app is running. On the other hand, I know there are many other launchers out there and they can all add widgets seamlessly, so there must be another approach to this.
Any advice would be greatly appreciated!
Cheers

Hope that the question is still open...
You do too much things within you method. Under specific circumstances you fire to events shorty one after the other. I am not working too long on android, so I can not tell you, whether this may be ok or not.
And you always fire the intent here:
Intent bindIntent = new Intent(AppWidgetManager.ACTION_APPWIDGET_BIND);
bindIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widget_id);
bindIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER, widget_provider.provider);
startActivityForResult(bindIntent, REQUEST_BIND_APPWIDGET);
The intent above causes the question most probarbly. You may check beforehand, whether you need to ask for permission or not. You can ask with this routine:
Boolean callProviderIntent = false;
if (checkCallProviderIntent)
{
callProviderIntent = true;
Method m = null;
try
{
m = AppWidgetManager.class
.getMethod("bindAppWidgetIdIfAllowed", new Class[]
{ Integer.TYPE, ComponentName.class });
}
catch (NoSuchMethodException e)
{
}
if (m != null)
{
try
{
callProviderIntent = !(Boolean) m
.invoke(mAppWidgetManager,
appWidgetId,
launcherAppWidgetInfo.provider);
}
catch (Exception e)
{
}
}
}
It is dummy code. And it uses reflection, since I am under Android 2.3.

This is the solution I finally found for my application.
AppWidgetManager manager = m.getAppWidgetManager();
AppWidgetHost host = m.getWidgetHost();
List<AppWidgetProviderInfo> widgetList = manager.getInstalledProviders();
AppWidgetProviderInfo provider = null;
for(AppWidgetProviderInfo info : widgetList){
//To get the google search box
if(info.provider.getClassName().equals("com.google.android.googlequicksearchbox.SearchWidgetProvider")){
provider = info;
break;
}
}
if(provider != null){
int id = host.allocateAppWidgetId();
boolean success = false;
success = manager.bindAppWidgetIdIfAllowed(id, provider.provider);
if (success) {
AppWidgetHostView hostView = host.createView(getActivity(), id, provider);
AppWidgetProviderInfo appWidgetInfo = manager.getAppWidgetInfo(id);
LauncherAppWidgetInfo info = new LauncherAppWidgetInfo(id);
info.hostView = hostView;
info.hostView.setAppWidget(id, appWidgetInfo);
attachWidget(info);
} else {
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_BIND);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, id);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER,
provider.provider);
// TODO: we need to make sure that this accounts for the options
// bundle.
// intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS,
// options);
m.startActivityForResult(intent, Main.REQUEST_BIND_APPWIDGET);
}
}
}

Related

What is the event listener for when UsbManager Request Permission is called to execute a routine when a permission is granted?

I'm stuck on figuring out how to ask for permission to access a USB com device, wait for the user input, then proceed accordingly if permission granted. I can't figure out what the "onRequestPermissionsResult" is for when UsbManager asks for permissions. I noticed that listener never gets called when UsbManager requests permission, so its not used in the way I originally thought.
This code is all in the MainActivity.
Here I'm setting my Intent for when my USB device is connected or disconnected, and initializing UsbManager.
Note I'm not using LOGCAT to log debug messages because my Android device has to be disconnected from Android Studio to plug in the USB com device I'm developing the app for. Instead I'm logging to the app UI.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DoIntent();
m_manager = (UsbManager) getSystemService(Context.USB_SERVICE);
}
private void DoIntent () {
m_usbReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action) || UsbManager.ACTION_USB_ACCESSORY_ATTACHED.equals(action)) {
try {
OnDeviceConnected();
// m_textViewDebug.setText("USB Connected");
} catch (Exception e) {
m_textViewDebug.setText(e.getMessage());
}
} else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action) || UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
m_port = null;
m_serialIoManager = null;
m_isInitialized = false;
m_textViewDebug.setText("USB Disconnected");
}
}
};
IntentFilter filter = new IntentFilter();
filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
registerReceiver(m_usbReceiver , filter);
Then here is what happens when a device is connected. I want to establish permission as soon as its connected.
private void OnDeviceConnected () throws Exception {
ProbeTable customTable = new ProbeTable();
customTable.addProduct(0x239a, 0x800c, CdcAcmSerialDriver.class);
UsbSerialProber prober = new UsbSerialProber(customTable);
List<UsbSerialDriver> drivers = prober.findAllDrivers(m_manager);
UsbDeviceConnection connection = null;
UsbSerialDriver driver = drivers.get(0);
PendingIntent usbPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(INTENT_ACTION_GRANT_USB), 0);
m_manager.requestPermission(driver.getDevice(), usbPermissionIntent);
/// Need some kind of pause or check for permissions here before executing forward.or
/// handle everything after on a different routine called after permission has been selected.
/// Continues to execute before user has time to respond to permissions.
try {
connection = m_manager.openDevice(driver.getDevice());
} catch (Exception e) {
throw new Exception(e.getMessage());
}
if (connection == null) {
throw new Exception ("Could not open device.");
}
m_port = driver.getPorts().get(0);
try {
m_port.open(connection);
m_port.setParameters(115200, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE);
m_port.setDTR(true);
} catch (Exception e) {
throw new Exception(e.getMessage());
}
m_serialIoManager = new SerialInputOutputManager(m_port, m_listener);
m_executor.submit(m_serialIoManager);
m_isInitialized = true;
}
Then here is what I'm originally trying to do once permission has been granted.
I can't get any logging message to appear from this scope, so I believe it's never being called and I'm using it incorrectly.
#Override
public void onRequestPermissionsResult(final int requestCode, String[] permissions, int[] grantResults) {
MainActivity.this.runOnUiThread(new Runnable() {
public void run() {
/// Never gets called :/
m_textViewDebug.setText(Integer.toString(requestCode));
}
});
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
/// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
/// permission was granted, yay! Do the
/// contacts-related task you need to do.
} else {
/// permission denied, boo! Disable the
/// functionality that depends on this permission.
}
return;
case USB_PERMISSION_GRANTED: { /// Not the real enum because I'm not sure where to find what it is.
try {
/// Need to somehow pass driver from OnDeviceConnected to this scope, or make it class property.
connection = m_manager.openDevice(driver.getDevice());
} catch (Exception e) {
throw new Exception(e.getMessage());
}
if (connection == null) {
throw new Exception ("Could not open device.");
}
m_port = driver.getPorts().get(0);
try {
m_port.open(connection);
m_port.setParameters(115200, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE);
m_port.setDTR(true);
} catch (Exception e) {
throw new Exception(e.getMessage());
}
m_serialIoManager = new SerialInputOutputManager(m_port, m_listener);
m_executor.submit(m_serialIoManager);
m_isInitialized = true
}
/// other 'case' lines to check for other
/// permissions this app might request.
}
}
I'm trying to log what requestCode is so I can write a case for whatever the USB permission code is. I can't find a compiled list anywhere in the docs of what all the options are that requestCode could be.
MY_PERMISSIONS_REQUEST_READ_CONTACTS actually throws a compile error because I have no idea where it comes from. This guide isn't very detail with USB specifically. That guide is also where I got the switch statement in my above routine.
EDIT:
I tried messing around with UsbManager.EXTRA_PERMISSION_GRANTED to see if that could work. I added it as an action to my intent filter.
IntentFilter filter = new IntentFilter();
filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
filter.addAction(UsbManager.EXTRA_PERMISSION_GRANTED);
registerReceiver(m_usbReceiver, filter);
Then I'm logging what the action of the intent is coming into my Broadcast Receiver, but nothing happens when a USB permission is granted or denied.
What kind of action or event is triggered when "OK" is tapped in this above image? Been scratching my head at this for a few days poking at the API.
I finally figured it out taking a closer look at this.
I have this before trying to establish an intent filter.
public static final String INTENT_ACTION_GRANT_USB = BuildConfig.APPLICATION_ID + ".GRANT_USB";
PendingIntent usbPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(INTENT_ACTION_GRANT_USB), 0);
IntentFilter filter = new IntentFilter();
And I changed it to this.
private static final String ACTION_USB_PERMISSION = BuildConfig.APPLICATION_ID + ".USB_PERMISSION";
m_permissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
The key difference was that new IntentFilter needed that ACTION_USB_PERMISSION string.
Now in my Broadcast Receiver, I have this condition that is being called as expected.
else if (ACTION_USB_PERMISSION.equals(action)) {
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
m_textViewDebug.setText("USB Permission Granted");
try {
OnDevicePermissionGranted();
} catch (Exception e) {
m_textViewDebug.setText(e.getMessage());
}
}
else {
m_textViewDebug.setText("USB Permission Denied");
}
}
Took me a while to figure out how to use EXTRA_PERMISSION_GRANTED.
When this here says "EXTRA_PERMISSION_GRANTED containing boolean indicating whether permission was granted by the user" I'm thinking this whole time I'm trying to find a boolean flag on some object to verify permission. I didn't realize I had to call a special method on the intent and supply that string to get my true or false. Seems very counter intuitive to me.
I realize the biggest mistake was not supplying the correct string when making the new intent filter. I found a bunch of other examples that had it without any arguments.

Read service name from AndroidManifest

I want to write Firebase's InstanceId service like service in my project. The project is an SDK where the developer who integrates it has the provision to override this service. In this case, I should be able to read the name of the new service specified by the developer with a particular action in their AndroidManifest.xml file.
So the real question here is, how can I read the name of the service declared in the AndroidManifest.xml file with a specific action?
Use below utility method
public static void startService(Context context, String lookupAction) {
Intent serviceIntent = new Intent();
serviceIntent.setAction(lookupAction);
serviceIntent.setPackage("package.of.your.application");
List<ResolveInfo> resInfo = context.getPackageManager().queryIntentServices(serviceIntent, 0);
if (resInfo != null && !resInfo.isEmpty()) {
ServiceInfo service = resInfo.get(0).serviceInfo;
ComponentName cmpService = new ComponentName(service.applicationInfo.packageName, service.name);
Intent serviceToStart = new Intent(lookupAction);
serviceToStart.setComponent(cmpService);
context.startService(serviceToStart);
} else {
// Handle error
}
}
I will add documentation soon

monitor file receiving via bluetooth

I'm now trying to transfer files between Android devices via bluetooth. I already implemented my sender side. I'm not using InputStream/OutputStream. I'm using Intent.ACTION_SEND. Everything in there sender side works fine, but when it comes to the receiver side, I'm facing two problems.
There's the pop out notification saying "Do you want to receive this file?". Is there any way I can avoid this thing?
How can I know that there's a file coming in and the file transfer is finished or stopped at the receiver side?
It seems that these two problems can be solved using InputStream/OutputStream, but I don't really want to use them. Maybe a listener that monitors Bluetooth, or some functions in BluetoothAdapter/BluetoothDevice can do this?
Thanks for help. My code is like below: (in my MainActivity.java)
public void beginBT() {
if (isSender) {
File file = new File(Environment.getExternalStorageDirectory().getPath()+"/log.txt");
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file));
if (!findBluetoothForIntent(intent)){
Toast.makeText(this, "Bluetooth Not Found.", Toast.LENGTH_SHORT).show();
} else {
//intent will send the file via bluetooth
startActivity(intent);
}
} else { //receiver side
//make device be discoverable
Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivity(discoverableIntent);
}
}
public boolean findBluetoothForIntent(Intent intent){
List appsList = getPackageManager().queryIntentActivities(intent, 0);
String packageName = null;
String className = null;
for (Object info: appsList){
if (info instanceof ResolveInfo) {
packageName = ((ResolveInfo) info).activityInfo.packageName;
if (packageName.equals("com.android.bluetooth")){
className = ((ResolveInfo) info).activityInfo.name;
break;
}
}
}
if (className != null) {
intent.setClassName(packageName, className);
return true;
} else {
return false;
}
}
Answering my own question is always so much fun!!
About the pop out notification, I can't do anything about it, unless I use InStream/OutStream.
For the receiver side, use BroadcastReceiver to monitor actions of the device. Here I monitor the disconnecting action of bluetooth. Because there will be a connecting action when the device begin to receive file, and when it finishes, there will be a disconnecting action.
Don't know if the following code would help anybody, :)
MainActivity.java
private static final String BT_DISCONNECTED = "android.bluetooth.device.action.ACL_DISCONNECTED";
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action == BT_DISCONNECTED) {
//now file transmitting has finished, can do something to the file
//if you know the file name, better to check if the file is actually there
// - make sure this disconnection not initiated by any other reason.
}
}
IntentFileter filter = new IntentFilter(BluetoothDevice.ACTION_ACL_DISCONNECTED);
this.registerReceiver(mReceiver, filter);
Warning: remember to unregister this receiver when you exit the activity, or simply when you don't need it

Check if a widget is exists on homescreen using appWidgetId

I am using AlarmManager to update my widgets. And I want to stop it if there is no widget on homescreen. But I am facing a problem with detecting if there is no widget on home screen.
As whenever I try to get the AppWidgetIds using this way:
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
int[] appWidgetIDs = appWidgetManager
.getAppWidgetIds(new ComponentName(context, Widget.class));
I get the a length of appWidgetIDs while actually there is no widget on homescreen. Why?
Therefore, I would like to know if there is a way to detect that a widget id is exists on homescreen.
Thank you upfront.
Congratulations, you've encountered phantom appwidgets. It appears to be documented on the Android issue tracker. They usually occur when the configuration activity for an appwidget is canceled, though it seems to be through improper implementation of the configuration activity; developers neglect to include the appwidget ID as an extra when setting the activity result to RESULT_CANCELED. (even Google's ApiDemos sample application neglects to do this!)
The proper implementation is like this:
public class AppWidgetConfigActivity extends Activity {
private int appWidgetId;
private Intent resultValue;
protected void onCreate(bundle saved) {
super.onCreate(saved);
// get the appwidget id from the intent
Intent intent = getIntent();
appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID);
// make the result intent and set the result to canceled
resultValue = new Intent();
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
setResult(RESULT_CANCELED, resultValue);
// if we weren't started properly, finish here
if (appwidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
finish();
}
/* ... */
}
/* ... */
private void finishConfigure() {
/* finish configuring appwidget ... */
setResult(RESULT_OK, resultValue);
}
}
Thus far I know of no way to detect the presence of a phantom appwidget without doing your own bookkeeping. I suggest storing a SharedPreferences value indicating that the configuration activity was not canceled and then querying this value in your other code. You can also use this information to "delete" a phantom widget if you come across one. In your appwidget configuration activity:
private void finishConfigure() {
/* finish configuring appwidget ... */
setResult(RESULT_OK, resultValue);
String key = String.format("appwidget%d_configured", appwidgetId);
SharedPreferences prefs = getSharedPreferences("widget_prefs", 0);
prefs.edit().putBoolean(key, true).commit;
}
Then you can check that you have at least one non-phantom appwidget like so:
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
AppWidgetHost appWidgetHost = new AppWidgetHost(context, 1); // for removing phantoms
SharedPreferences prefs = getSharedPreferences("widget_prefs", 0);
boolean hasWidget = false;
int[] appWidgetIDs = appWidgetManager.getAppWidgetIds(new ComponentName(context, Widget.class));
for (int i = 0; i < appWidgetIDs.length; i++) {
int id = appWidgetIDs[i];
String key = String.format("appwidget%d_configured", id);
if (prefs.getBoolean(key, false)) {
hasWidget = true;
} else {
// delete the phantom appwidget
appWidgetHost.deleteAppWidgetId(id);
}
}
if (hasWidget) {
// proceed
} else {
// turn off alarms
}

Check Widget is Placed on Android Screen

Can someone tell me how to check that my widget have been placed on the homescreen?
I have some code in my app that should run only if the widget is placed on the homescreen.
Just saying, but...
int ids[] = AppWidgetManager.getInstance(this).getAppWidgetIds(new ComponentName(this,MyAppWidgetProvider.class));
Toast.makeText(this, "Number of widgets: "+ids.length, Toast.LENGTH_LONG).show();
You need to store that information yourself. I usually use the application preferences, but you could use anything. Generally widgets use services to communicate, so your code that does stuff is likely in a service, but using the preference allows any portion of your app to access this.
In your widget class that extends AppWidgetProvider the onEnabled is called when the widget is put on a homescreen and the onDeleted is (usually) called when it's removed. onDisabled is called when all copies are removed.
So in the code of your widget provider:
#Override
public void onEnabled(Context context) {
super.onEnabled(context);
setWidgetActive(true);
context.startService(new Intent(appContext, WidgetUpdateService.class));
}
#Override
public void onDisabled(Context context) {
Context appContext = context.getApplicationContext();
setWidgetActive(false);
context.stopService(new Intent(appContext, WidgetUpdateService.class));
super.onDisabled(context);
}
private void setWidgetActive(boolean active){
Context appContext = context.getApplicationContext();
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(appContext);
SharedPreferences.Editor edit = prefs.edit();
edit.putBoolean(Constants.WIDGET_ACTIVE, active);
edit.commit();
}
Elsewhere in code, you would check to see if the widget is active by:
public boolean isWidgetActive(Context context){
Context appContext = context.getApplicationContext();
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
return prefs.getBoolean(Constants.WIDGET_ACTIVE, false);
}
I know it's an old question, but looking at this today I saw that there are a couple of problems with the accepted answer from #larsona1:
if the user cleared the shared preferences - there's still widget, but the app won't know about it.
if the user regret between "add widget" and before pressing "ok" - onEnabled will be called anyway, and a widget will be registered in the home screen even though there is no widget, and no way to remove it later. (it may be a bug in ADT home launcher).
I found a solution to the first problem.
No shared preferences are needed at all, since it's unreliable anyway. It has to be checked in runtime.
// in some class you define a static variable, say in S.java
static boolean sWidgetMayExist = true;
In your widget provider:
// MyAppWidgetProvider.java
// to respond to runtime changes, when widgets are added and removed
#Override
public void onEnabled(Context context) {
super.onEnabled(context);
S.sWidgetMayExist = true;
}
#Override
public void onDisabled(Context context) {
super.onDisabled(context);
S.sWidgetMayExist = true;
}
And, in your service code add this:
AppWidgetManager manager = null;
RemoteViews views = null;
ComponentName widgetComponent = null;
// ..and in your update thread
if (!S.sWidgetMayExist) { return; }
if (manager == null || widgetComponent == null) {
widgetComponent = new ComponentName(c,
MyAppWidgetProvider.class);
manager = AppWidgetManager.getInstance(c);
}
if (manager.getAppWidgetIds(widgetComponent) == null) {
S.sWidgetMayExist = false;
}
#Waza_Be is right as looking at the "AppWidgetIds" list to know the number of active widgets (those installed on your homescreen) is the correct way to know this information.
However, keep in mind that you SHOULD don't have to look at this by yourself.
Check the official Android documentation for best practice about widgets :
https://developer.android.com/guide/topics/appwidgets/index.html#AppWidgetProvider
The right approach is to override only the onUpdate() method and iterate through the list of "active" widgets :
public class ExampleAppWidgetProvider extends AppWidgetProvider {
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
final int N = appWidgetIds.length;
// Perform this loop procedure for each App Widget that belongs to this provider
for (int i=0; i<N; i++) {
int appWidgetId = appWidgetIds[i];
// Create an Intent to launch ExampleActivity
Intent intent = new Intent(context, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
// Get the layout for the App Widget and attach an on-click listener
// to the button
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget_provider_layout);
views.setOnClickPendingIntent(R.id.button, pendingIntent);
// Tell the AppWidgetManager to perform an update on the current app widget
appWidgetManager.updateAppWidget(appWidgetId, views);
}
}
}
And as your own widget provider overrides AppWidgetProvider, you will NOT go into the onUpdate() method if you have no widgets active on the home screen!
See the onReceive() code of Android AppWidgetProvider that checks already for you that "appWidgetIds.length > 0":
public void onReceive(Context context, Intent intent) {
// Protect against rogue update broadcasts (not really a security issue,
// just filter bad broacasts out so subclasses are less likely to crash).
String action = intent.getAction();
if (AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)) {
Bundle extras = intent.getExtras();
if (extras != null) {
int[] appWidgetIds = extras.getIntArray(AppWidgetManager.EXTRA_APPWIDGET_IDS);
if (appWidgetIds != null && appWidgetIds.length > 0) {
this.onUpdate(context, AppWidgetManager.getInstance(context), appWidgetIds);
}
}
}
(...)
}
What about the following:
boolean widgetExists(Context context, int appWidgetId) {
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
AppWidgetProviderInfo info = appWidgetManager.getAppWidgetInfo(appWidgetId);
return (info != null);
}
From the docs for appWidgetManager.getAppWidgetInfo():
If the appWidgetId has not been bound to a provider yet, or you don't have access to that appWidgetId, null is returned.

Categories

Resources