I'm trying to add a widget into my app and I am facing a problem. Whenever I grab the widget and place it on my homescreen, it just disappears. I can only see it for about 0.5 seconds. Here is the code:
Manifest.xml
<receiver
android:label="MyApp"
android:name=".widget.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>
MyWidgetProvider.java
public class MyWidgetProvider extends AppWidgetProvider {
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
//IDs
for (int i=0; i<appWidgetIds.length; i++) {
int currentWidgetId = appWidgetIds[i];
// Create data
SharedPreferences prefs = context.getSharedPreferences("com.example.app_preferences", 0);
int number = prefs.getInt("progress", 0);
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
R.layout.appwidget);
Log.w("WidgetExample", String.valueOf(number));
// Set the text
remoteViews.setTextViewText(R.id.widgettext, 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.widgettext, pendingIntent);
appWidgetManager.updateAppWidget(currentWidgetId, remoteViews);
Toast.makeText(context, "widget added", Toast.LENGTH_SHORT).show();
}
}
}
appwidget.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/widgetlayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/widgetimage" >
<TextView
android:id="#+id/widgettext"
style="#android:style/TextAppearance.Medium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true" />
</RelativeLayout>
widget_info.xml
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:updatePeriodMillis="86400000"
android:minWidth="120dp"
android:minHeight="50dp"
android:initialLayout="#layout/appwidget"
android:previewImage="#drawable/widgetimage"
android:configure="com.example.app.widget.MyWidgetProvider" >
</appwidget-provider>
you can see the last line of the java file contains a toast. This toast actually gets called and there are no errors whatsoever in the logcat.
Thanks!
You're android:configure element must refer to an activity that will allow configuration of your widget. This activity must set result to RESULT_OK, otherwise configuration is cancelled and widget is removed.
I suppose referring to your widget provider, not an activity, has the same effect of returning RESULT_CANCEL from the configuration activity.
If you don't have a configuration activity, simply remove this entry and the widget will be added without trying to open such.
Another possibility other than 3c71's answer is that you might have forgotten to use the two-parameter version of setResult(int resultCode, Intent data). The data parameter has to include an EXTRA which identifies the widget ID.
Intent intent = new Intent();
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
setResult(RESULT_OK, intent);
sendBroadcast(intent);
The widget ID is provided to the configuration activity as an EXTRA in the Intent that is supplied to the activity when it is called. Retrieve it and store it like this:
mAppWidgetId = getIntent().getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
Related
I'm trying to set a timer on the phone (not in the app I created) using ACTION_SET_TIMER intent and I'm not sure why it's not working when I click the button it either restarts the app or crashes it. Thanks for the help!
<Button
android:id="#+id/timer_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:onClick="startTimer"
android:text="#string/timer_note"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/camera_button"
/>
public void startTimer(View view) {
String searchFor = ((EditText) findViewById(R.id.share_edittext)).getText().toString();
String strNew = searchFor.replaceFirst("You ordered a ", "");
int seconds = 10;
Intent intent = new Intent(AlarmClock.ACTION_SET_TIMER)
.putExtra(AlarmClock.EXTRA_MESSAGE, strNew)
.putExtra(AlarmClock.EXTRA_LENGTH, seconds)
.putExtra(AlarmClock.EXTRA_SKIP_UI, true);
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
else {
Log.d("ImplicitIntents", "Can't handle this intent!");
}
}
After further digging I realized I needed to add a permission to the Manifest.XML file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.homework">
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
This is my first time asking a question on SO.
I want to pass my Calculation object to the widget to be displayed on the home screen. I have the widget to update in my MainActivity.java when I click the calculate button:
I'm using Parceler.
Here is my widget after clicking the Calculate button
And the MainActivity
My issue is that the widget is not displaying the calculation info that was supposedly passed to it from the Provider class. it seems to parcelize correctly in my logs that display the calculation, just that I may be setting the widget view incorrectly to receive the data and display it.
public void saveCalcInfo(View v){
[...]
setWidget(calculation);
}
private void setWidget(Calculation calculationToPassToWidget) {
BullAppWidgetProvider.manualUpdateWidgets(getApplicationContext(), calculationToPassToWidget);
}
All I really need from the widget is to receive the calculation info, and display it.
A nice to have would be upon clicking the button "View", launch the MainActivity and autofill the EditTexts with the displayed information about the calculation
Here's my BullAppWidgetProvider.java
public class BullAppWidgetProvider extends AppWidgetProvider {
static void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Calculation calculation) {
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_provider);
if (calculation != null) {
views.setTextViewText(R.id.symbol, calculation.getSymbol());
views.setTextViewText(R.id.shares, String.valueOf(calculation.getShares()));
views.setTextViewText(R.id.buy, String.valueOf(calculation.getBuy()));
views.setTextViewText(R.id.sell, String.valueOf(calculation.getSell()));
views.setTextViewText(R.id.comm, String.valueOf(calculation.getComm()));
}
Intent intent = new Intent(context, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, appWidgetId, intent, PendingIntent.FLAG_UPDATE_CURRENT);
views.setOnClickPendingIntent(R.id.viewCalcBT, pendingIntent);
views.setTextViewText(R.id.widget_app_title, context.getString(R.string.widget_prompt));
appWidgetManager.updateAppWidget(appWidgetId, views);
}
static void manualUpdateWidgets(Context context, Calculation calculation) {
ComponentName componentName = new ComponentName(context, BullAppWidgetProvider.class);
Timber.w("Calculation received in manual Update: %s", calculation.toString());
AppWidgetManager manager = AppWidgetManager.getInstance(context);
int[] appWidgetIds = manager.getAppWidgetIds(componentName);
for (int appWidgetId : appWidgetIds) {
updateAppWidget(context, manager, appWidgetId, calculation);
Toast.makeText(context, "Widget has updated!", Toast.LENGTH_LONG).show();
}
}
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
for (int appWidgetId : appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId, null);
}
}
}
If needed, here's the
widget_layout.xml
file for reference
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:background="#color/primary">
<TextView
android:id="#+id/symbol"
style="#style/AdapterStyle"
android:text="#string/ipl" />
<TextView
android:id="#+id/shares"
style="#style/AdapterStyle"
android:layout_alignParentEnd="true"
android:text="#string/_42" />
<TextView
android:id="#+id/buy"
style="#style/AdapterStyle"
android:layout_below="#id/symbol"
android:text="#string/buy" />
<TextView
android:id="#+id/sell"
style="#style/AdapterStyle"
android:layout_below="#id/buy"
android:text="#string/sell" />
<TextView
android:id="#+id/comm"
style="#style/AdapterStyle"
android:layout_below="#id/shares"
android:layout_alignParentEnd="true"
android:text="#string/comm" />
<Button
android:id="#+id/viewCalcBT"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/sell"
android:layout_alignParentEnd="true"
android:text="#string/view" />
</RelativeLayout>
as well as the
widget_provider.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="8dp">
<TextView
android:id="#+id/widget_app_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="#string/app_name" />
<
android:id="#+id/ll_parent_for_widget"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
Thank you for your time!
In the documentation for the new "Pinned Shortcuts" feature in Android O, they mention that "You can also create a specialized activity that helps users create shortcuts, complete with custom options and a confirmation button".
I tried following the documentation, but when I tried to create a new shortcut I only saw the default dialog, and not my activity.
Here's the declaration in the Manifest:
<activity android:name=".ShortcutActivity">
<intent-filter>
<action android:name="android.intent.action.CREATE_SHORTCUT"/>
</intent-filter>
</activity>
P.S
In the documentation they also shows an example in the Gmail app - how do I get to that screen? I wanted to see the flow but I couldn't find it.
You have to create a new activity as dialog, then you can add whatever options you want on that dialog and handle as you want the addShortcut method.
I tried that code to add and remove a dynamical shortcut and it worked.
AndroidManifest.xml
<activity android:name=".DialogActivity"
android:excludeFromRecents="true"
android:theme="#style/Theme.AppCompat.Dialog"
>
...
</activity>
DialogActivity.java
public class DialogActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dialog);
this.setFinishOnTouchOutside(false);
findViewById(R.id.add_button).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
addShortcut();
}
});
findViewById(R.id.cancel_button).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
finish();
}
});
}
...
}
activity_dialog.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_dialog"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.metax.myapplication.DialogActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Do you want to add shortcut?"/>
<Button
android:id="#+id/cancel_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_alignParentStart="true"
android:text="No thanks"/>
<Button
android:id="#+id/add_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_alignParentEnd="true"
android:text="Add me"/>
</RelativeLayout>
In you Java class insert
ShortcutManager sM = c.getSystemService(ShortcutManager.class);
Intent intent2 = new Intent(c.getApplicationContext(), ShortcutActivity.class);
intent2.setAction(Intent.ACTION_VIEW);
ShortcutInfo shortcut2 = new ShortcutInfo.Builder(c,MSG_SHORCUT_CUSTOM)
.setIntent(intent2)
.setShortLabel("ShortLabel")
.setLongLabel("LongLaber")
.setDisabledMessage("DisabledMessage")
.setIcon(Icon.createWithResource(c, R.mipmap.ic_add_outline_short))
.build();
listshortcut.add(shortcut2);
Intent pinnedShortcutCallbackIntent = mShortcutManager.createShortcutResultIntent(shortcut2);
PendingIntent successCallback = PendingIntent.getBroadcast(context, 0, pinnedShortcutCallbackIntent, 0);
mShortcutManager.requestPinShortcut(pinShortcutInfo, successCallback.getIntentSender());
sM.setDynamicShortcuts(listshortcut);
To launch your shortcut activity with action as ACTION_CREATE_SHORTCUT, long tap on app icon, and press widget icon, you ll notice a 1x1 widget, on tap of which your desired activity would be launched.
Also you can explicitly fire that intent from your app as well on some desired action.
Create a new resource file: res/xml/shortcuts.xml. This is how you create shortcuts,After you have done the nessicary changes in manifest
<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
<shortcut
android:shortcutId="compose"
android:enabled="true"
android:icon="#drawable/compose_icon"
android:shortcutShortLabel="#string/compose_shortcut_short_label1"
android:shortcutLongLabel="#string/compose_shortcut_long_label1"
android:shortcutDisabledMessage="#string/compose_disabled_message1">
<intent
android:action="android.intent.action.VIEW"
android:targetPackage="your package"
android:targetClass="com.example.myapplication.ComposeActivity" />
</shortcut>
<!-- Specify more shortcuts here. -->
</shortcuts>
In manifest add this to the activity tag,
<meta-data android:name="android.app.shortcuts"
android:resource="#xml/shortcuts" />
If you want to read more refer this doc it explains about pinned shortcuts, static and dynamic shortcuts.
Here is an example from google, in their samples repo
I've created a widget, and on click an Activity has to be launched, I followed the answer to this question [Clickable widgets in android].
However, on click I am unable to get any response, here is the java code to my widget:
Widget.java
public class Widget extends AppWidgetProvider
{
private static String YOUR_AWESOME_ACTION = "YourAwesomeAction";
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
{
Intent intent = new Intent(context, HomeTeamSelector.class);
intent.setAction(YOUR_AWESOME_ACTION);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget);
views.setOnClickPendingIntent(R.id.widgetLayout, pendingIntent);
}
#Override
public void onReceive(Context context, Intent intent)
{
super.onReceive(context, intent);
if (intent.getAction().equals(YOUR_AWESOME_ACTION))
{
Intent x = new Intent(context,HomeTeamSelector.class);
context.startActivity(x);
}
}
}
This is the code to the xml file:
widget.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:id="#+id/widgetLayout"
android:layout_height="match_parent"
android:transitionGroup="true">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/app_name_extra"
android:id="#+id/textView"
android:layout_centerInParent="true"
android:textColor="#color/colorPrimary"
android:textSize="30sp" />
</RelativeLayout>
The widget is rendered, however I am unable to get any response on click, what is possibly causing this, and how to fix?
try to add AppWidgetProvider receiver in AndroidMenifest.xml like
<receiver
android:name=".Widget"
android:label="#string/widget">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/widget" />
</receiver>
This is only my second time using widgets, and first time using buttons on it... or anything other than just TextViews in general.
So basically all I have is a widget... When I click it it doesn't do anything and it never updates. Why? Confused... :P
So, here is my WidgetAct onUpdate code:
#Override
public void onUpdate(Context c, AppWidgetManager awm, int[] appWidgetIds){
Log.i("IN","onUpdate");
RemoteViews rv = new RemoteViews(c.getPackageName(),R.layout.widget);
Intent twitter_intent = new Intent(c,TwitterUpdate.class);
twitter_intent.setAction(ACTION_WIDGET_TWITTER);
Intent fb_intent = new Intent(c,FBUpdate.class);
fb_intent.setAction(ACTION_WIDGET_FB);
//Intent curr = new Intent(c,WidgetAct.class);
//curr.setAction(ACTION_WIDGET_WA);
PendingIntent twitter_pi = PendingIntent.getActivity(c, 0, twitter_intent, 0);
PendingIntent fb_pi = PendingIntent.getActivity(c,0,fb_intent,0);
rv.setOnClickPendingIntent(R.id.tweet, twitter_pi);
rv.setOnClickPendingIntent(R.id.fb, fb_pi);
awm.updateAppWidget(appWidgetIds, rv);
}
Now here is my manifest (or the important part):
<receiver android:name="WidgetAct">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="com.laytproducts.IN.WidgetAct.ACTION_WIDGET_FB" />
<action android:name="com.laytproducts.IN.WidgetAct.ACTION_WIDGET_TWITTER" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="#xml/winfo"/>
</receiver>
Here is my xml for the widget provider:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth = "220dp"
android:minHeight = "72dp"
android:updatePeriodMillis="0"
android:initialLayout="#layout/widget">
Here is my layout:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/linearLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<FrameLayout android:background="#drawable/inwidget" android:id="#+id/frameLayout1" android:layout_width="wrap_content" android:layout_height="wrap_content">
<RelativeLayout android:id="#+id/relativeLayout1" android:layout_width="fill_parent" android:layout_height="fill_parent">
<ImageButton android:scaleType="fitXY" android:src="#drawable/twitterlogo" android:layout_marginTop="17dp" android:id="#+id/tweet" android:layout_marginLeft="20dp" android:layout_width="40dp" android:layout_height="40dp"></ImageButton>
<ImageButton android:scaleType="fitXY" android:src="#drawable/facebooklogo" android:layout_marginLeft="5dp" android:id="#+id/fb" android:layout_toRightOf="#+id/tweet" android:layout_alignTop="#+id/tweet" android:layout_alignBottom="#+id/tweet" android:layout_width="40dp" android:layout_height="40dp"></ImageButton>
</RelativeLayout>
</FrameLayout>
Kind of a lot of code... but I literally have NO reason to believe that I broke something XD... but that is because my widget knowledge is minimal.
Hopefully its a small mistake I over looked.
Thanks all,
Brandon
If you want your widget to update, you should have to set the time interval in "updatePeriodMillis" field in the XML file .But remember ,the minimum time interval for updating using this method is 30 min.
According to the explanation in the SDK document, the onUpdate() method is designed to respond to the ACTION_APPWIDGET_UPDATE broadcast, which will be sent in conditions below:
Sent when it is time to update your AppWidget.
This may be sent in response to a new instance for this AppWidget provider having been instantiated, the requested update interval having lapsed, or the system booting.
In your code, you set the action com.laytproducts.IN.WidgetAct.ACTION_WIDGET_FB, so the onUpdate() won't be called. I haven't used getActivity in widget, but I have used getBroadcast and it works well.
PendingIntent fb_pi = PendingIntent.getBroadcast(c,0,fb_intent,0);
I think you should handle your click event in the onReceive() method. Please note that the AppWidgetProvider extends from BroadcastReceiver, so only onReceive() will be called(in the onReceive() in the source code of AppWidgetProvider, onUpdate() is called inside. That's why we have onUpdate()). You should do something like:
#Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
String action = intent.getAction();
if (action.equals("com.laytproducts.IN.WidgetAct.ACTION_WIDGET_FB")) {
//handle your click event here
}
}
This is what I did in my widget. Hope it helps.
You can try this..
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget);
Intent one = new Intent(context, TwitterUpdate.class);
Intent two = new Intent(context, FBUpdate.class);
PendingIntent p1 = PendingIntent.getActivity(context, 0, one, 0);
PendingIntent p2 = PendingIntent.getActivity(context, 0, two, 0);
remoteViews.setOnClickPendingIntent(R.id.twitter_pi, p1);
remoteViews.setOnClickPendingIntent(R.id.fb_pi, p2);
appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);
}