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>
Related
I am trying to update my widget's TextView Text from a BroadcastReceiver on ClickPendingIntent. I am not having much luck. Can I please get some help with this? In my ActionReceiver.class which extends BroadcastReceiver, I know that I need to update the widget after changing the textview text. I am not sure how to do that. Unfortunately, I can't use statics without crashing the app and widget. Here is my code...
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.mywidget">
<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">
<receiver android:name=".MyWidget">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/my_widget_info" />
</receiver>
<activity
android:name=".MainActivity"
android:screenOrientation="locked">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".ActionReceiver"/>
</application>
</manifest>
activity_main.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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="#+id/myTV"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textAlignment="center"
android:text="#string/default_tv_text"
android:textSize="16sp"
android:textStyle="bold"
android:textColor="#android:color/black"/>
<EditText
android:id="#+id/myET"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/myTV"
android:inputType="text"
android:hint="#string/default_et_text"
android:textAlignment="center"
android:textSize="16sp"
android:textStyle="bold"
android:textColor="#android:color/black"
tools:ignore="Autofill" />
<View
android:id="#+id/myView"
android:layout_width="match_parent"
android:layout_height="5dp"
android:layout_below="#id/myET"/>
<Button
android:id="#+id/myButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/myView"
android:layout_centerHorizontal="true"
android:text="#string/button_text"
android:textSize="16sp"
android:textStyle="bold"
android:textColor="#android:color/black"/>
</RelativeLayout>
my_widget.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="180dp"
android:layout_height="110dp"
android:padding="#dimen/widget_margin">
<TextView
android:id="#+id/appwidget_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_margin="8dp"
android:contentDescription="#string/appwidget_text"
android:text="#string/appwidget_text"
android:textColor="#android:color/white"
android:textSize="24sp"
android:textStyle="bold|italic" />
</RelativeLayout>
strings.xml
<resources>
<string name="app_name">My Widget</string>
<string name="default_tv_text">Hello World!</string>
<string name="default_et_text">Enter Something To Change The Text Above.</string>
<string name="button_text">OK</string>
<string name="appwidget_text">EXAMPLE</string>
<string name="appwidget_text_changed">Hello World!</string>
<string name="add_widget">Add widget</string>
</resources>
MainActivity.class
package com.example.mywidget;
import androidx.appcompat.app.AppCompatActivity;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
TextView tv;
EditText et;
Button btn;
#Override
protected void onDestroy() {
super.onDestroy();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = findViewById(R.id.myTV);
et = findViewById(R.id.myET);
btn = findViewById(R.id.myButton);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String getEditText = et.getText().toString();
if (!getEditText.isEmpty()) {
tv.setText(getEditText);
Toast.makeText(getBaseContext(), "Text Changed!", Toast.LENGTH_SHORT).show();
}
}
});
}
}
MyWidget.class
package com.example.mywidget;
import android.app.PendingIntent;
import android.app.Service;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.widget.RemoteViews;
import android.widget.Toast;
import androidx.annotation.Nullable;
public class MyWidget extends AppWidgetProvider {
public void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
int appWidgetId) {
CharSequence widgetText = context.getString(R.string.appwidget_text);
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.my_widget);
views.setTextViewText(R.id.appwidget_text, widgetText);
Intent actionIntent = new Intent(context, ActionReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, actionIntent, PendingIntent.FLAG_UPDATE_CURRENT);
views.setOnClickPendingIntent(R.id.appwidget_text, pi);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
for (int appWidgetId : appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId);
}
}
}
ActionReceiver.class
package com.example.mywidget;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.RemoteViews;
import android.widget.Toast;
public class ActionReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
CharSequence getNewText = context.getString(R.string.appwidget_text_changed);
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.my_widget);
views.setTextViewText(R.id.appwidget_text, getNewText); // The widget needs to be updated from here with something like this updateAppWidget(context, appWidgetManager, appWidgetId);
Toast.makeText(context, "Widget Updated!", Toast.LENGTH_SHORT);
}
}
My Updated MyWidget.class
public class MyWidget extends AppWidgetProvider {
public void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
int appWidgetId) {
CharSequence widgetText = context.getString(R.string.appwidget_text);
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.my_widget);
views.setTextViewText(R.id.appwidget_text, widgetText);
Intent actionIntent = new Intent(context, MyWidget.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, actionIntent, PendingIntent.FLAG_UPDATE_CURRENT);
views.setOnClickPendingIntent(R.id.appwidget_text, pi);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
for (int appWidgetId : appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId);
}
}
#Override
public void onReceive(Context context, Intent intent) {
AppWidgetManager appWM = AppWidgetManager.getInstance(context);
ComponentName myWidget = new ComponentName(context, MyWidget.class);
int[] appWIDs = appWM.getAppWidgetIds(myWidget);
CharSequence getNewText = context.getString(R.string.appwidget_text_changed);
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.my_widget);
views.setTextViewText(R.id.appwidget_text, getNewText);
if (appWIDs == null && appWIDs.length > 0) {
onUpdate(context, appWM, appWIDs);
Toast.makeText(context, "Widget Updated!", Toast.LENGTH_SHORT).show();
}
}
}
It's still not working for me. When I click the textview on the widget, it just launches the app. I'm trying to get the textview to change the default word "Example" to "Hello World" when the textview is clicked on. I've been trying for hours figuring this out.
I am developing an Android app consisting of two activites so far. The first activity (MainActivity) is started when the app is launched or when a QR code is scanned. The MainActivity starts the second activity (NFCActivity) when the user presses a button. The NFCActivity waits for the user to tap a NFC token, reads out data from the token, and returns the read data to the MainActivity.
This works fine if the app is started manually. If the app is started by scanning a QR code, taping the NFC tag does not invoke the NFCActivity's onNewIntent() method as exepcted, but instead creates a new instance of the NFCActivity on top of the already displayed one.
The enableForegroundDispatch() method is called and FLAG_ACTIVITY_SINGLE_TOP should be set. Relevant source code of a minimal example is provided below. Any help would be highly appreciated!
MainActivity:
public class MainActivity extends Activity {
private EditText dataRead;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start);
dataRead = (EditText) findViewById(R.id.data);
final Button readKeyButton = (Button) findViewById(R.id.readNFC);
readKeyButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent keyIntent = new Intent(MainActivity.this,
NFCActivity.class);
keyIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivityForResult(keyIntent, 1);
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode,
Intent intent) {
if (requestCode == 1) {
String result = intent.getExtras().getString("resultData");
this.dataRead.setText(result);
}
}
}
Main Activity's GUI:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<Button
android:id="#+id/readNFC"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="127dp"
android:text="Read NFC Tag" />
<EditText
android:id="#+id/data"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="#+id/readNFC"
android:layout_centerHorizontal="true"
android:layout_marginBottom="85dp"
android:ems="10" >
<requestFocus />
</EditText>
</RelativeLayout>
NFCActivity:
public class NFCActivity extends Activity {
private NfcAdapter mAdapter;
private PendingIntent pendingIntent;
private IntentFilter[] mFilters;
private String[][] mTechLists;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.read_nfc);
mAdapter = NfcAdapter.getDefaultAdapter(this);
pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this,
getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
// // Setup an intent filter for all MIME based dispatches
IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
try {
ndef.addDataType("*/*");
} catch (MalformedMimeTypeException e) {
throw new RuntimeException("fail", e);
}
IntentFilter td = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
mFilters = new IntentFilter[] { ndef, td };
//
// // Setup a tech list for all NfcF tags
mTechLists = new String[][] { new String[] { NfcV.class.getName(),
NfcF.class.getName(), NfcA.class.getName(),
NfcB.class.getName() } };
}
#Override
public void onResume() {
super.onResume();
if (mAdapter != null)
mAdapter.enableForegroundDispatch(this, pendingIntent, mFilters,
mTechLists);
}
#Override
public void onPause() {
super.onPause();
if (mAdapter != null)
mAdapter.disableForegroundDispatch(this);
}
#Override
public void onNewIntent(Intent intent) {
Log.d("TEST", "onNewIntent() called.");
// READ THE NFC TAG HERE [SKIPPED FOR MINIMAL EXAMPLE]
// Return dummy data for test
Intent result = new Intent();
result.putExtra("resultData", "DUMMY DATA");
setResult(1, result);
finish();
}
}
NFCActivity's GUI:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#303030"
android:paddingLeft="30dp"
android:paddingRight="30dp" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="Tap your NFC tag.."
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="#FF8811"
android:textSize="30sp"
android:textStyle="bold" />
</RelativeLayout>
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="test.nfcqrtest"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="18" />
<uses-permission android:name="android.permission.NFC" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="test.nfcqrtest.MainActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="myapp" android:host="test.org" android:pathPrefix="/testapp" />
</intent-filter>
</activity>
<activity
android:name=".NFCActivity"
android:windowSoftInputMode="stateHidden" android:screenOrientation="portrait" android:launchMode="singleTop">
</activity>
</application>
</manifest>
In case somebody is facing a similar problem: I was finally able to overcome the issue described above by setting the android:launchMode property for the MainActivity to singleInstance.
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);
I am currently learning about widgets in Android.
I want to be able to update my textview, but each time when I try to update it - my program crashes.
Here is my class:
public class DayWidget extends AppWidgetProvider {
public static CheckDate CheckDate;
public static EventList EventList;
public static String EVENT_CLICK = "EventClick";
public String msg;
public RemoteViews views;
public AppWidgetManager manager;
public Context cntxt;
public Intent intnt;
public int[] ids;
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds){
super.onUpdate(context, appWidgetManager, appWidgetIds);
CheckDate = new CheckDate();
EventList = new EventList();
manager = appWidgetManager;
views = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
ids = appWidgetIds;
Intent intent = new Intent(context, DayWidget.class);
intent.setAction(EVENT_CLICK);
intent.putExtra("msg", "change");
PendingIntent actionPendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
views.setOnClickPendingIntent(R.id.Event, actionPendingIntent);
CheckDate.Check();
views.setTextViewText(R.id.Today, CheckDate.Today);
manager.updateAppWidget(ids, views);
}
public void UpdateWidget(){
Bundle extras = intnt.getExtras();
if(extras!=null) {
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(cntxt);
ComponentName AppWidget = new ComponentName(cntxt.getPackageName(), DayWidget.class.getName());
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(AppWidget);
views.setTextViewText(R.id.Event, "New text");
onUpdate(cntxt, appWidgetManager, appWidgetIds);
}
}
public void onReceive(Context context, Intent intent){
intnt = intent;
cntxt = context;
if(EVENT_CLICK.equals(intent.getAction())){
try{
msg = intent.getStringExtra("msg");
}catch(NullPointerException e){
e.printStackTrace();
}
UpdateWidget();
//Toast toast = Toast.makeText(cntxt, "TEST", Toast.LENGTH_LONG);
//toast.show();
}
super.onReceive(context, intent);
}
}`
Manifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.sunmille.day"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="9"
android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<receiver
android:name="DayWidget">
<intent-filter>
<action
android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action
android:name="android.appwidget.action.ACTION_WIDGET_RECEIVER" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/widget_data" />
</receiver>
</application>
Widget data
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="294dp"
android:minHeight="72dp"
android:minResizeWidth="294dp"
android:minResizeHeight="72dp"
android:updatePeriodMillis="0"
android:resizeMode="horizontal|vertical"
android:initialLayout="#layout/widget_layout">
Widget layout
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#drawable/widget_background" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center" >
<TextView
android:id="#+id/TopText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Cегодня "
android:textIsSelectable="false"
android:textColor="#000000"
android:textSize="20sp"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="#+id/Today"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textIsSelectable="false"
android:textColor="#000000"
android:textSize="20sp"
android:textAppearance="?android:attr/textAppearanceLarge" />
</LinearLayout>
<TextView
android:id="#+id/Event"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textIsSelectable="false"
android:textColor="#000000"
android:textSize="20sp"
android:text="Some event"
android:textAppearance="?android:attr/textAppearanceLarge" />
Log:
03-29 14:10:15.954: E/AndroidRuntime(4552): java.lang.RuntimeException: Unable to start receiver com.sunmille.day.DayWidget: java.lang.NullPointerException
03-29 14:10:15.954: E/AndroidRuntime(4552): at com.sunmille.day.DayWidget.UpdateWidget(DayWidget.java:61)
03-29 14:10:15.954: E/AndroidRuntime(4552): at com.sunmille.day.DayWidget.onReceive(DayWidget.java:77)
CORRECT CODE:
public class DayWidget extends AppWidgetProvider {
public static CheckDate CheckDate;
public static EventList EventList;
public static String EVENT_CLICK = "EventClick";
public String msg;
public RemoteViews rviews;
public AppWidgetManager manager;
public Context cntxt;
public Intent intnt;
public int[] ids;
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds){
super.onUpdate(context, appWidgetManager, appWidgetIds);
CheckDate = new CheckDate();
EventList = new EventList();
manager = appWidgetManager;
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
ids = appWidgetIds;
Intent intent = new Intent(context, DayWidget.class);
intent.setAction(EVENT_CLICK);
intent.putExtra("msg", "change");
PendingIntent actionPendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
views.setOnClickPendingIntent(R.id.Event, actionPendingIntent);
CheckDate.Check();
views.setTextViewText(R.id.Today, CheckDate.Today);
manager.updateAppWidget(ids, views);
}
public void UpdateWidget(){
Bundle extras = intnt.getExtras();
if(extras!=null) {
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(cntxt);
ComponentName AppWidget = new ComponentName(cntxt.getPackageName(), DayWidget.class.getName());
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(AppWidget);
rviews = new RemoteViews(AppWidget.getPackageName(), R.layout.widget_layout);
rviews.setTextViewText(R.id.Event, "New text");
appWidgetManager.updateAppWidget(appWidgetIds, rviews);
}
}
public void onReceive(Context context, Intent intent){
intnt = intent;
cntxt = context;
if(EVENT_CLICK.equals(intent.getAction())){
try{
msg = intent.getStringExtra("msg");
}catch(NullPointerException e){
e.printStackTrace();
}
UpdateWidget();
Toast toast = Toast.makeText(cntxt, "TEST", Toast.LENGTH_LONG);
toast.show();
}
super.onReceive(context, intent);
}
}
Variable views of type RemoteViews is null. You can see it on Logcat output.
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);
}