I'm trying to launch my MainActivity from my AppWidget with pending intent but I can't figure out why it doesn't fire the intent. The widget has a ListView with up to 3 items, which is bind to a RemoteViewsService. I want to start my MainActivity when any of the rows is clicked. Can anyone tell me what I might done wrong?
I already checked some related posts like this Launching an activity from an AppWidget, and even tried to run the sample from here https://github.com/commonsguy/cw-advandroid/tree/master/AppWidget, and while the sample works, still can't tell what I did differently.
Here are some of my code that are relevant, please let me know if I should post more, and apologize in advance if my post doesn't look right as this is my first question:
Widget layout:
<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/stocks"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
AppWidgetProvider class:
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
Log.d(LOGTAG, "onUpdate");
Log.d(LOGTAG, "appWidgetIds.length="+appWidgetIds.length);
for (int i = 0; i < appWidgetIds.length; ++i) {
Log.d(LOGTAG, "appWidgetIds[i]="+appWidgetIds[i]);
}
// update each of the app widgets with the remote adapter
for (int i = 0; i < appWidgetIds.length; ++i) {
updateWidget(context, appWidgetManager, appWidgetIds[i]);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
public void updateWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {
Log.d(LOGTAG, "updateWidget id="+appWidgetId);
// Sets up the intent that points to the StackViewService that will
// provide the views for this collection.
Intent intent = new Intent(context, StockAppWidgetService.class);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
// When intents are compared, the extras are ignored, so we need to embed the extras
// into the data so that the extras will not be ignored.
intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.stock_appwidget);
rv.setRemoteAdapter(R.id.stocks, intent);
Intent contentIntent = new Intent(context, MainActivity.class);
//contentIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent startAppPendingIntent =
PendingIntent.getActivity(context, 0, contentIntent, 0);
rv.setPendingIntentTemplate(R.id.stocks, startAppPendingIntent);
appWidgetManager.updateAppWidget(appWidgetId, rv);
}
manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="x40241.chris.yuan.a4.app"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="16" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#android:style/Theme.Holo.Light.DarkActionBar" >
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".SearchableActivity" >
<intent-filter>
<action android:name="x40241.chris.yuan.a4.app.SEARCH" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<service android:name=".StockServiceImpl" />
<service android:name=".StockAppWidgetService"
android:permission="android.permission.BIND_REMOTEVIEWS" />
<receiver android:name=".ServiceLauncher">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<receiver android:name=".StockAppWidgetProvider" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="#xml/stock_appwidget_info" />
</receiver>
</application>
</manifest>
I think I found the answer, or at least a workable solution in a related post:
AdapterViewFlipper in app widget: setPendingIntentTemplate() and setOnClickFillInIntent() not working
It turns out I wasn't setting the FillInIntent properly. I should call setOnClickFillInIntent on the top level view of the list item instead of the list itself. Here's the code change that made it work in RemoteViewsFactory:
public RemoteViews getViewAt(int position) {
if (DEBUG) Log.d(LOGTAG, "StockRemoteViewsFactory getViewAt position="+position);
RemoteViews rv = new RemoteViews(mContext.getPackageName(), R.layout.widget_item);
rv.setTextViewText(R.id.text_symbol, mStockItems.get(position).getSymbol());
rv.setTextViewText(R.id.text_price, String.format("$%.2f", mStockItems.get(position).getPrice()));
Intent fillInIntent = new Intent(Intent.ACTION_MAIN);
fillInIntent.putExtra(StockAppWidgetProvider.ITEM_NUM, position);
// set on the top level view of the list item, instead of the list view itself
//rv.setOnClickFillInIntent(R.id.stocks, fillInIntent);
rv.setOnClickFillInIntent(R.id.general_layout, fillInIntent);
return rv;
}
Related
I want to open an activity from widget and another activity from application launcher. Both the activity should show in recent task at once. Currently the current activity override the previous opened activity. I want both activity in recent task.
Please find the codes here:
public class SimpleAppWidget extends AppWidgetProvider {
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
for(int i=0; i<appWidgetIds.length; i++){
int appWidgetId = appWidgetIds[i];
Intent intent = new Intent(context, SecondActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pending = PendingIntent.getActivity(context, 0,intent, 0);
RemoteViews views = new RemoteViews(context.getPackageName(),R.layout.activity_main);
views.setOnClickPendingIntent(R.id.btnClick, pending);
appWidgetManager.updateAppWidget(appWidgetId,views);
Toast.makeText(context, "widget added", Toast.LENGTH_SHORT).show();
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="hcl.mobility.testwidget">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/Theme.TestWidget">
<activity
android:name=".MainActivity"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".SecondActivity"
android:launchMode="singleTask" />
<receiver android:name="hcl.mobility.testwidget.SimpleAppWidget">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/simple_app_widget_info" />
</receiver>
</application>
</manifest>
<appwidget-provider
xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="146dp"
android:updatePeriodMillis="0"
android:minHeight="146dp"
android:initialLayout="#layout/activity_main">
</appwidget-provider>
app launcher activity in recent task
widget activity in recent task
I want to show both activity in recent task.
delete android:launchMode="singleTask"
addFlags
Intent intent = new Intent(context, SecondActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
startActivity(intent);
I'm sure I'm missing something simple here but onGetViewFactory is not calling while attempting to populate a StackWidget. I've gone over this multiple times and cannot find my error.
The RemoteViewsService is being attached in updateWidget:
public static void updateWidget(Context context, AppWidgetManager appWidgetManager, int widgetId) {
// Create the RemoteViews to represent the widget layout.
Log.i(TAG, "updateWidget: Creating RemoteViews");
RemoteViews widgetViews = new RemoteViews(context.getPackageName(), R.layout.stack_widget_layout);
// Create an intent that points to our widget service.
Log.i(TAG, "updateWidget: Creating Intent");
Intent remoteIntent = new Intent(context, StackWidgetService.class);
// Attach that intent to the RemoteViews as our remote adapter.
Log.i(TAG, "updateWidget: Setting Adapter");
widgetViews.setRemoteAdapter(R.id.stack_view, remoteIntent);
// Set which view should be used as the empty view.
Log.i(TAG, "updateWidget: Setting empty view");
widgetViews.setEmptyView(R.id.stack_view, R.id.text_empty);
// Update the widget.
Log.i(TAG, "updateWidget: Updating widget");
appWidgetManager.updateAppWidget(widgetId, widgetViews);
}
The following should be called after calling appWidgetManager.updateAppWidget but is not:
#Override
public RemoteViewsFactory onGetViewFactory(Intent intent) {
// NOT CALLED
Log.i(TAG, "onGetViewFactory: Creating new view factory");
return new StackWidgetViewFactory(getApplicationContext());
}
As far as I can tell, my manifest is correct:
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".stackwidget.StackWidgetProvider"
android:exported="true">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="#xml/stack_widget_info" />
</receiver>
<service android:name=".stackwidget.StackWidgetService"
android:exported="true"
android:permission="android.permission.BIND_REMOTEVIEWS"/>
</application>
And here is my stack_widget_info.xml, for safety:
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="250dp"
android:minHeight="180dp"
android:updatePeriodMillis="1800000"
android:initialLayout="#layout/stack_widget_layout"
android:autoAdvanceViewId="#layout/stack_item"
android:widgetCategory="home_screen"
android:resizeMode="horizontal |vertical">
</appwidget-provider>
The issue was actually in my widget layout. Constraint layout was causing issues. It runs correctly when changing over to Linear layout.
I'm trying to build a hello world widget and I followed three different examples and every time my apk loads the main activity as an app and not a widget. In the last example it showed a manifest with no activity block. When I take the main activity out of the manifest and just have the receiver block Android Studio throws an exception of Default activity not found. So that is the one difference I have from the example. I have an <*activity> block in the manifest.
I'm in Android Studio 1.0.2. What could be causing this?
My current code is based on this example
http://www.vogella.com/tutorials/AndroidWidgets/article.html
http://www.sitepoint.com/how-to-code-an-android-widget/
https://looksok.wordpress.com/2012/12/15/android-complete-widget-tutorial-including-source-code/
AndroidMainfest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.me.countdown" >
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name="MyWidgetProvider" >
<intent-filter >
<action
android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/widget_info" />
</receiver>
</application>
</manifest>
MyWidgetProvider.xml
public class MyWidgetProvider extends AppWidgetProvider {
private static final String ACTION_CLICK = "ACTION_CLICK";
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
// Get all ids
ComponentName thisWidget = new ComponentName(context,
MyWidgetProvider.class);
int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
for (int widgetId : allWidgetIds) {
// create some random data
int number = (new Random().nextInt(100));
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
R.layout.widget_layout);
Log.w("WidgetExample", String.valueOf(number));
// Set the text
remoteViews.setTextViewText(R.id.update, String.valueOf(number));
// Register an onClickListener
Intent intent = new Intent(context, MyWidgetProvider.class);
intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.update, pendingIntent);
appWidgetManager.updateAppWidget(widgetId, remoteViews);
}
}
}
widget_info.xml under res/xml
\<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider
xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="#layout/widget_layout"
android:minHeight="72dp"
android:minWidth="300dp"
android:updatePeriodMillis="300000" >
</appwidget-provider>
I'm not sure what those other examples are designed for, but the version of Android Studio I'm using - 1.2.2 - does it differently. I found the example below and was able to get a working shell of a widget, which is what I wanted. Even this one needed many small tweaks before it would compile and run, but I did get it.
Greg
http://www.clearcreekcode.com/create-a-widget-in-android-studio/
I have an application and I have also created an app widget for it. The app widget is just a shortcut to launch application.
My manifestfile:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.hansem.handbookmanual"
android:installLocation="internalOnly"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="19" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:exported="true"
android:theme="#style/AppTheme" >
<receiver android:name="com.example.HandbookAppWidgetProvider" android:label="abc">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider" android:resource="#xml/widget1_info" />
</receiver>
<activity
android:name="com.example.BrowserLauncherActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Widget1_info.xml
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="72dp"
android:minHeight="72dp"
android:minResizeHeight="72dp"
android:resizeMode="vertical"
android:updatePeriodMillis="0"
android:initialLayout="#layout/widget1">
</appwidget-provider>
Widget1.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/button_applaunch"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="4dp"
android:background="#drawable/ic_launcher"
android:gravity="center"
android:orientation="vertical" >
</LinearLayout>
I have tried all the solution mentioned on Stackflow but noting helped. On restarting the device, the widget gets added, but normally by just installing the app on phone and launching it, the widget is not added.
AppWidgetProviderCode:
public class HandbookAppWidgetProvider extends AppWidgetProvider {
DateFormat df = new SimpleDateFormat("hh:mm:ss");
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
final int N = appWidgetIds.length;
Log.i("ExampleWidget", "Updating widgets " + Arrays.asList(appWidgetIds));
// 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, BrowserLauncherActivity.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.widget1);
views.setOnClickPendingIntent(R.id.button_applaunch, pendingIntent);
// To update a label
//views.setTextViewText(R.id.widget1label, df.format(new Date()));
// Tell the AppWidgetManager to perform an update on the current app
// widget
appWidgetManager.updateAppWidget(appWidgetId, views);
}
}
}
Please help
My problem is I have an app widget which needs to be updated in every 32 mins. However, it's not updating the textview. I placed Log entry to my onUpdate method to see is it working on Logcat, and i confirmed method is working properly but just it's not changing the value of textview. Here is my code;
AppWidgetProvider:
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
// TODO Auto-generated method stub
ComponentName thisWidget=new ComponentName(context,
IzUlasimProvider.class);
int[] allWidgetIds=appWidgetManager.getAppWidgetIds(thisWidget);
for(int id:allWidgetIds){
String now=new SimpleDateFormat("HH:mm").format(new Date());
RemoteViews views=new RemoteViews(context.getPackageName(), R.layout.widget);
views.setTextViewText(R.id.tvWidget,now);
appWidgetManager.updateAppWidget(id, views);
now=null;
}
Log.w("Update","Update Finished");
}
My config file:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="#layout/widget"
android:minHeight="110dp"
android:updatePeriodMillis="1920000"
android:minWidth="250dp" android:configure="com.izulasim.widget.IzWidgetConfig">
AndroidManifest part for the widget:
<receiver android:name="com.izulasim.widget.IzWidgetProvider">
<intent-filter >
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="#xml/widget_config" />
</receiver>
<activity
android:name="com.izulasim.widget.IzWidgetConfig"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
</intent-filter>
</activity>
<provider android:name=".IzUlasimProvider"
android:authorities="com.izulasim.provider.IzUlasim" />