Android Widget won't start a Service - android

I need to make a widget which, once clicked, would start a service. Service would perform a certain action, change the widgets picture, play a sound, etc., and stop.
AppWidgetProvider:
public class WidgetActivity extends AppWidgetProvider {
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
Intent intent = new Intent(context.getApplicationContext(), SilentService.class);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
PendingIntent pendingIntent = PendingIntent.getService(
context.getApplicationContext(), 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.LinLayWiget, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);
context.startService(intent);
}
}
service:
public class SilentService extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
Toast.makeText(this, "I'm Alive!", 1500).show();
MediaPlayer mpl = MediaPlayer.create(this, R.raw.enter );
mpl.start();
}
#Override
public void onDestroy() {
//code to execute when the service is shutting down
}
#Override
public void onStart(Intent intent, int startid) {
//code to execute when the service is starting up
}
}
manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="FX.Widget"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="8" />
<application android:icon="#drawable/icon" android:label="#string/app_name">
<receiver android:name="widget.cam.com.WidgetActivity" android:label="FXMaster" android:icon="#drawable/assiconwi">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="android.appwidget.action.APPWIDGET_ENABLED"/>
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/widgetprovider" />
</receiver>
<service
android:enabled="true"
android:name=".SilentService">
</service>
</application>
</manifest>
But once I click on the widget, nothing happens... any ideas why?
Thanks!

Related

onReceive() in widget dosen't fired in api>26 [duplicate]

My widget app is running fine on all android version except 8 Oreo.
I get a W/BroadcastQueue: Background execution not allowed: receiving Intent message.
There is an interesting blog from CommonsWare but I don't fully understand why it applies to my case.
https://commonsware.com/blog/2017/04/11/android-o-implicit-broadcast-ban.html
My case looks pretty simple: I have a widget with a button and I want to change the text's button when it is clicked.
What is the right way to fix this issue?
TestWidget.java
public class TestWidget extends AppWidgetProvider {
private static RemoteViews views;
private static boolean buttonClicked = false;
public static final String ACTION_AUTO_UPDATE = "AUTO_UPDATE";
#Override
public void onReceive(Context context, Intent intent)
{
super.onReceive(context, intent);
if(intent.getAction().equals(ACTION_AUTO_UPDATE))
{
Log.i("TESTWID", "get onReceive");
}
}
static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
int appWidgetId) {
views = new RemoteViews(context.getPackageName(), R.layout.test_widget);
views.setOnClickPendingIntent(R.id.wid_btn_tst, setButton(context));
appWidgetManager.updateAppWidget(appWidgetId, views);
}
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
Log.i("TESTWID", "onupdate ");
for (int appWidgetId : appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId);
}
}
public static PendingIntent setButton(Context context) {
Intent intent = new Intent();
intent.setAction("TEST");
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
public static void pushWidgetUpdate(Context context, RemoteViews remoteViews) {
ComponentName myWidget = new ComponentName(context, TestWidget.class);
AppWidgetManager manager = AppWidgetManager.getInstance(context);
manager.updateAppWidget(myWidget, remoteViews);
}
}
TestWidgetReceiver.java
public class TestWidgetReceiver extends BroadcastReceiver{
private static boolean isButtonON = false;
#Override
public void onReceive(Context context, Intent intent) {
Log.i("TESTWID", "onReceive "+intent.getAction());
if(intent.getAction().equals("TEST")){
updateWidgetButton(context, 2);
}
}
private void updateWidgetButton(Context context, int index) {
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.test_widget);
if(index == 2) {
if(isButtonON) {
remoteViews.setTextViewText(R.id.wid_btn_tst, "Test Off");
isButtonON = false;
}
else{
remoteViews.setTextViewText(R.id.wid_btn_tst, "Test On");
isButtonON = true;
}
}
TestWidget.pushWidgetUpdate(context.getApplicationContext(), remoteViews);
}
}
Manifest.xml:
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="Test"
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=".TestWidget">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<intent-filter>
<action android:name="AUTO_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/test_widget_info" />
</receiver>
<receiver
android:name=".TestWidgetReceiver"
android:label="widgetBroadcastReceiver" >
<intent-filter>
<action android:name="TEST" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/test_widget_info" />
</receiver>
</application>
It's subtle, but it is because of the implicit broadcast being used to trigger your TestWidgetReceiver. It is implicit because it is only specifying the action portion of the Intent. Make the broadcast Intent explicit by specifying the receiver class in the constructor:
public static PendingIntent setButton(Context context) {
Intent intent = new Intent(context, TestWidgetReceiver.class);
intent.setAction("TEST");
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
Things are changed now a days in Android. For the security & battery consumption google introduced so many ways & increased some problem for developers.
You haven't passed the Context of the TestWidgetReceiver.class to you intent.
You can do it like that in java
Intent intent = new Intent(context, TestWidgetReceiver.class);
or in kotlin
val intent = Intent(context, TestWidgetReceiver.class);
You can read more changes here
https://developer.android.com/about/versions/oreo/android-8.0-changes
Regards

My App widget's Remoteview's receiver getting call randomly

I am beginner in working with app widget. Here i have made one app widget of app and in its class set receiver on click of widget icon.Its working when user clicks on it.But the issue is receiver also gets called sometimes automatically.
I am not getting why this is happening.Help will be appreciated.
My app widget's class:
MyWidget.java:
public class MyWidget extends AppWidgetProvider {
static Context cont;
static SharedPreferences preferences;
static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
int appWidgetId) {
preferences = context.getSharedPreferences("pref", Context.MODE_PRIVATE);
cont = context;
Intent intent2 = new Intent(context, MyReceiver.class);
PendingIntent pendingIntent = PendingIntent.
getBroadcast(context, 0,
intent2, PendingIntent.FLAG_UPDATE_CURRENT);
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.my_widget);
views.setOnClickPendingIntent(R.id.appwidget_text, pendingIntent);
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 onEnabled(Context context) {
preferences = context.getSharedPreferences("pref", Context.MODE_PRIVATE);
preferences.edit().putBoolean("key", true).commit();
}
#Override
public void onDisabled(Context context) {
preferences = context.getSharedPreferences("pref", Context.MODE_PRIVATE);
preferences.edit().putBoolean("key", false).commit();
}
#Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
}
}
Manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="*************************">
<application
android:allowBackup="true"
android:icon="#drawable/logo"
android:label="#string/app_name"
android:roundIcon="#drawable/logo"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".Home">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".Myservice" />
<receiver android:name=".MyReceiver"></receiver>
<receiver android:name=".MyWidget">
<intent-filter>
<action android:name="**********************" />
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/my_widget_info" />
</receiver>
</application>
</manifest>

Update widget onClick, start service does not seem to work

I've followed a bunch of tutorials, search on google and on stack overflow and came up with this code to update my widget when i touch it:
public class WidgetService extends Service{
#Override
public void onStart(Intent intent, int startId) {
Log.i("WidgetService", "Called");
String fakeUpdate = null;
Random random = new Random();
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this
.getApplicationContext());
int[] appWidgetIds = intent
.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);
if (appWidgetIds.length > 0) {
for (int widgetId : appWidgetIds) {
int nextInt = random.nextInt(100);
fakeUpdate = "Random: " + String.valueOf(nextInt);
RemoteViews remoteViews = new RemoteViews(getPackageName(),
R.layout.widget);
remoteViews.setTextViewText(R.id.txt_updated, fakeUpdate);
appWidgetManager.updateAppWidget(widgetId, remoteViews);
}
stopSelf();
}
super.onStart(intent, startId);
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
And for widget provider:
public class Widget extends AppWidgetProvider{
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds){
RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
R.layout.widget);
Intent intent = new Intent(context.getApplicationContext(),
WidgetService.class);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
PendingIntent pendingIntent = PendingIntent.getService(
context.getApplicationContext(), 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.cnt_widget, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);
context.startService(intent);
}
}
In manifest:
<receiver
android:label="#string/next_trip_text"
android:name=".widget.Widget" >
<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>
And xml:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="272dp"
android:minHeight="72dp"
android:updatePeriodMillis="0"
android:initialLayout="#layout/widget"
android:configure="se.webevo.basttrafik.widget.WidgetConfigActivity" >
</appwidget-provider>
The service doesn't seem to be called at all. Any ideas? :)
Thanks!
add this to manifest:
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/-- ur appwidgetprovider location here--">
</meta-data>
also try adding:
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_ENABLED"/>
</intent-filter>
see if it works

android AppWidget buttons unbinding

I have a widget that lets you select from 2 sizes, it also has a config. For some reason after some time goes by, the buttons on my widget will unbind and you will not be able to click anything. I dont know why this is happening. Could it be the super.onReceive(context, intent) in my OnRecieve method? Would that cause it to unbind possibly? Also what would the sure fire way to make sure the buttons are ALWAYS binded be?
AppWidgetProvider
public class mWidget extends AppWidgetProvider {
public static String ACTION_WIDGET_REFRESH = "Refresh";
public static final String PREFS_NAME = "mWidgetPrefs";
#Override
public void onEnabled(Context context) {
}
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
RemoteViews remoteViews = buildLayout(context);
appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);
}
public static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
int appWidgetId) {
RemoteViews views = buildLayout(context);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
public static RemoteViews buildLayout(Context context) {
RemoteViews remoteView = new RemoteViews(context.getPackageName(),
R.layout.widget_4x2);
Intent intent = new Intent(context, mWidget.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
intent, 0);
intent = new Intent(context, mWidget.class);
intent.setAction(ACTION_WIDGET_REFRESH);
pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
remoteView.setOnClickPendingIntent(R.id.refresh, pendingIntent);
return remoteView;
}
#Override
public void onReceive(Context context, Intent intent) {
RemoteViews remoteView = null;
remoteView = new RemoteViews(context.getPackageName(),
R.layout.widget_4x2);
if (intent.getAction().equals(ACTION_WIDGET_REFRESH)) {
Toast.makeText(context, "here", Toast.LENGTH_LONG).show();
} else {
super.onReceive(context, intent);
}
}
}
Manifest
<?xml version="1.0" encoding="utf-8"?>
<application android:icon="#drawable/icon" android:label="#string/app_name">
<activity android:name=".mwidgetConfig" android:label="#string/app_name"
android:theme="#android:style/Theme.NoTitleBar">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
</intent-filter>
</activity>
<activity android:name=".mwidgetConfigSmall"
android:label="#string/app_name" android:theme="#android:style/Theme.NoTitleBar">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
</intent-filter>
</activity>
<!-- BEGIN 4X4 WIDGET -->
<receiver android:label="Test Widget 4x4"
android:name="com.test.mwidget.mWidget">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action
android:name="com.test.mwidget.mWidget.ACTION_WIDGET_REFRESH" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="#xml/widget_4x4_provider" />
</receiver>
<!-- BEGIN 4X2 WIDGET -->
<receiver android:label="Test Widget 4x2"
android:name="com.test.mwidget.mWidgetSmall">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action
android:name="com.test.mwidget.mWidgetSmall.ACTION_WIDGET_REFRESH" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="#xml/widget_4x2_provider" />
</receiver>
</application>
You should bind your pending intent on each onUpdate event.
You should iterate through all appWidgerIds.
Usually, I implement widget stuff as the following:
public void onUpdate(Context context,
AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
updateAllWidgetsInternal(context, appWidgetManager, appWidgetIds);
}
private static void updateAllWidgetsInternal(Context context,
AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
final RemoteViews views = buildLayout(context);
final int N = appWidgetIds.length;
for (int i=0; i<N; ++i) {
appWidgetManager.updateAppWidget(appWidgetIds[i], views);
}
}
// This function can be executed anywhere in any time to update widgets
public static void updateAllWidgets(Context context) {
final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
final int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, mWidget.class));
updateAllWidgetsInternal(context, appWidgetManager, appWidgetIds);
}
I don't understand why you implemented onReceive().
It's only necessary if your widget is configured to catch other broadcasts than the standard widgets broadcast which are ACTION_APPWIDGET_DELETED, ACTION_APPWIDGET_DISABLED, ACTION_APPWIDGET_ENABLED and ACTION_APPWIDGET_UPDATE.
If not necessary, try without onReceive().

Android Widget Click and Broadcast Receiver Not Working

The below code should describe an app where once the widget button is clicked, it sends off an intent that should be received by TestReceiver. However, in running my below code, the onReceive of TestReceiver is never called.
Could someone let me know what I'm doing wrong?
Widget code
public class Widget 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.getApplicationContext(), TestReceiver.class);
Intent intent = new Intent();
intent.setAction(TestReceiver.TEST_INTENT);
intent.setClassName(TestReceiver.class.getPackage().getName(), TestReceiver.class.getName());
PendingIntent pendingIntent = PendingIntent.getBroadcast(context.getApplicationContext(), 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
// Get the layout for the App Widget and attach an on-click listener to the button
RemoteViews views;
views = new RemoteViews(context.getPackageName(), R.layout.main);
views.setOnClickPendingIntent(R.id.btnTest, pendingIntent);
// Tell the AppWidgetManager to perform an update on the current App Widget
appWidgetManager.updateAppWidget(appWidgetId, views);
}
}
}
Receiver Code:
public class TestReceiver extends BroadcastReceiver {
public static final String TEST_INTENT= "MyTestIntent";
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Toast.makeText(context, "Test", Toast.LENGTH_SHORT);
if(intent.getAction()==TEST_INTENT)
{
System.out.println("GOT THE INTENT");
Toast.makeText(context, "Test", Toast.LENGTH_SHORT);
}
}
}
Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.test.intenttest"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="#drawable/icon" android:label="#string/app_name">
<receiver android:name=".TestReceiver" android:label="#string/app_name">
<intent-filter>
<action android:name="MyTestIntent">
</action>
</intent-filter>
</receiver>
<receiver android:label="#string/app_name" android:name="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>
</application>
<uses-sdk android:minSdkVersion="3" />
</manifest>
It probably works, but you forgot to add .show() at the end of your Toast :)
== tests for reference equality (whether they are the same object).
.equals() tests for value equality (whether they are logically "equal").
String values are compared using '==' not 'equals'
This "if(intent.getAction()==TEST_INTENT)" change this "if(intent.getAction().equals(TEST_INTENT))"
and of course Toast.makeText(context, "Test", Toast.LENGTH_SHORT).show();
All code:
package *********;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class TestReceiver extends BroadcastReceiver {
public static final String TEST_INTENT= "MyTestIntent";
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Toast.makeText(context, "Test holaaa", Toast.LENGTH_SHORT).show();
if(intent.getAction() == TEST_INTENT)
// if(intent.getAction().equals(TEST_INTENT))
{
System.out.println("GOT THE INTENT");
Toast.makeText(context, "Test Goooo", Toast.LENGTH_SHORT).show();
}
}
}

Categories

Resources