Whenever I reboot my phone or upgrade the app (on my test device and on Android emulator) the widget stops updating until I create a new instance of the widget. Then both instances of the widget will start updating again. I assume it's something with calling the onUpdate() on old WidgetIds, but I can't figure it out.
Here's a small snipped of my code.
public class NewAppWidget extends AppWidgetProvider {
private static final String refresh = "b_refresh";
static void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.new_app_widget);
Intent intent = new Intent(context, NewAppWidget.class);
intent.setAction(refresh);
intent.putExtra("appWidgetId", appWidgetId);
views.setOnClickPendingIntent(R.id.refresh, PendingIntent.getBroadcast(context,0,intent, PendingIntent.FLAG_UPDATE_CURRENT));
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) {
if(refresh.equals(intent.getAction())) {
Toast.makeText(context, "Clicked2", Toast.LENGTH_LONG).show();
}
}
}
EDIT: Here's my manifest.xml
<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=".NewAppWidget">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="android.appwidget.action.EXTRA_APPWIDGET_IDS"/>
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/new_app_widget_info" />
</receiver>
<activity android:name=".NewAppWidgetConfigureActivity">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
</intent-filter>
</activity>
</application>
Add a call to super.onReceive() to your onReceive().
Explanation
If you look at the source for the base class onReceive(), you can see that it implements part of the framework logic for managing Widget lifecycle. (Also hinted at by the docs). It handles APPWIDGET_UPDATE and is, in fact, what's responsible for calling onUpdate() in the first place. (E.g., when the system boots up, and it needs to draw your initial widget, it sends your app an APPWIDGET_UPDATE, which gets passed to onReceive()). So, I'm not 100% sure how onUpdate() was ever getting called, in your case, but I assume you have some code somewhere else that calls updateAppWidget(), and that's the only reason your widgets appeared to work even momentarily.
Related
As long as I don't turn the phone off (even if the application is closed), the forward notification that I have created with the alarm manager in my android-java mobile application does not have a problem. But when I restart the phone before the notification time comes, it doesn't work even if it's time for my notification. Can you please help? Thanks.
MY ALARM SERVICE CLASS
package com.gokhankopuz.kopuzfilo.services;
public class AlarmService {
private Context context = null;
private long timeInMillis = 0L;
private String notificationTitle, notificationDesc = "";
public AlarmService(Context context, long timeInMillis, String notificationTitle, String notificationDesc) {
this.context = context;
this.timeInMillis = timeInMillis;
this.notificationTitle = notificationTitle;
this.notificationDesc = notificationDesc;
}
public void setAlarm() {
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, timeInMillis, getPendingIntent());
}
private PendingIntent getPendingIntent() {
#SuppressLint("UnspecifiedImmutableFlag")
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, (int) timeInMillis, getIntent(), PendingIntent.FLAG_UPDATE_CURRENT);
return pendingIntent;
}
private Intent getIntent() {
Intent intent = new Intent(context, AlarmReceiver.class);
intent.putExtra("notificationTitle", notificationTitle);
intent.putExtra("notificationDesc", notificationDesc);
return intent;
}
}
MY ALARM RECEIVER CLASS
package com.gokhankopuz.kopuzfilo.receivers;
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
buildNotification(context, intent);
}
private void buildNotification(Context context, Intent intent) {
String notificationTitle = intent.getStringExtra("notificationTitle");
String notificationDesc = intent.getStringExtra("notificationDesc");
Notify.build(context)
.setImportance(Notify.NotifyImportance.HIGH)
.setTitle(notificationTitle)
.setContent(notificationDesc)
.setColor(R.color.app_background)
.setSmallIcon(R.mipmap.ic_launcher)
.setAutoCancel(false)
.show();
}
}
MY MANIFEST
<?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="com.gokhankopuz.kopuzfilo">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"
tools:ignore="CoarseFineLocation" />
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:requestLegacyExternalStorage="true"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/Theme.KopuzFilo"
tools:ignore="AllowBackup">
<activity
android:name=".activities.NavigationActivity"
android:configChanges="orientation|screenSize|keyboardHidden"
android:exported="true" />
<activity
android:name=".activities.MainActivity"
android:exported="true"
android:configChanges="orientation|screenSize|keyboardHidden"
android:windowSoftInputMode="stateVisible|adjustPan" />
<activity
android:name=".activities.SplashActivity"
android:configChanges="orientation|screenSize|keyboardHidden"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".receivers.AlarmReceiver" />
</application>
</manifest>
I added the following permissions to my manifest file but it didn't work
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<receiver android:name=".MyReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>
This is the expected behavior. If you turn off your device, all alarms are deleted. So, to workaround this issue, you must register for boot complete broadcast and re-schedule your alarm.
You can find more details on how to do it in the following question/answer:
does Alarm Manager persist even after reboot?
I think you can try use work manager, which will be executed by system.
WorkManager is the recommended solution for persistent work. Work is persistent when it remains scheduled through app restarts and system reboots. Because most background processing is best accomplished through persistent work, WorkManager is the primary recommended API for background processing.
I try to launch a service at boot, but it never starts the service. I added <action android:name="android.intent.action.ACTION_POWER_CONNECTED"/> to the intent-filter of the receiver, but when I connect my android 8.0 phone to power, it also doesn't work.
manifest:
<?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="com.madmagic.oqrpc">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<application
android:usesCleartextTraffic="true"
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" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".MainService" />
<receiver
android:name=".StartAtBoot">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
</intent-filter>
</receiver>
</application>
</manifest>
StartAtBoot:
public class StartAtBoot extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "received", Toast.LENGTH_LONG).show(); //this never shows up when connecting to power
Intent i = new Intent(context, MainService.class);
context.startService(i);
}
}
MainService:
public class MainService extends Service {
public static boolean isRunning = false;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
isRunning = true;
Toast.makeText(this, "Service started", Toast.LENGTH_LONG).show();
ConnectionChecker.run(this); //when device has wifi connection, this will run connected() method
}
#Override
public void onDestroy() {
isRunning = false;
}
public void connected() {
//things to do when it has wifi connection
}
}
In my MainActivity class, I start this service using the same way as in my StartAtBoot class, and there it works fine when I open the application. So the service is working fine, its just that the StartAtBoot class doesn't run the code.
ACTION_POWER_CONNECTED is not a listed exception to the limits on implicit Intent broadcasts. Your app cannot register for it in the manifest.
If your goal is to do work periodically, but only if the device has power, use JobScheduler or WorkManager.
I have to create application and want to use it always when phone works, currently my code is:
Android Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.plan.pedometer">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
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>
<service android:enabled="true"
android:name=".PedometerService"/>
<receiver
android:name=".receiver.StartPedometerServiceAtBootReceiver"
android:label="StartPedometerServiceAtBootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
</manifest>
StartPedometerServiceAtBootReceiver:
public class StartPedometerServiceAtBootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
Intent serviceIntent = new Intent(context, PedometerService.class);
context.startService(serviceIntent);
}
}
}
Service:
public class PedometerService extends IntentService {
private int Steps=0;
public PedometerService() {
super("Pedometer_Worker_Thread");
}
#Override
protected void onHandleIntent(Intent intent) {
putInSharedPreferences();
synchronized (this) {
try {
wait(1000000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void putInSharedPreferences(){
stepsNumbers = getApplicationContext().getSharedPreferences("stepsData", MODE_PRIVATE);
editorStepsNumbers=stepsNumbers.edit();
editorStepsNumbers.putInt(String.valueOf(STEPS),Steps).apply();
}
}
It works if I start Service in MainActivity by:
Intent intent = new Intent(getApplication(),PedometerService.class);
startService(intent);
and Service is running in background but when I restart my phone nothing happens and Service does not start.
I have one more question, this is Pedometer application, where should I put onSensorChange method in Service? Create something like while(1) in onHandleIntent() and put it there?
UPDATE - my actually code is:
I followed this tutorial https://github.com/codepath/android_guides/wiki/Starting-Background-Services
and tried to use WakefulBroadcastReceiver
AndroidManifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.plan.pedomoter">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
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>
<service
android:name="com.plan.pedomoter.MyTestService"
android:exported="false"/>
<receiver android:name="com.plan.pedomoter.BootBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
</manifest>
MainActivity:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
protected void onStart() {
super.onStart();
launchTestService();
}
public void launchTestService() {
// Construct our Intent specifying the Service
Intent i = new Intent(this, MyTestService.class);
// Add extras to the bundle
i.putExtra("foo", "bar");
// Start the service
startService(i);
}
}
Receiver:
public class BootBroadcastReceiver extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// Launch the specified service when this message is received
Intent startServiceIntent = new Intent(context, MyTestService.class);
startWakefulService(context, startServiceIntent);
}
}
Service:
public class MyTestService extends IntentService {
Handler handler;
// Must create a default constructor
public MyTestService() {
// Used to name the worker thread, important only for debugging.
super("test-service");
}
#Override
public void onCreate() {
super.onCreate(); // if you override onCreate(), make sure to call super().
// If a Context object is needed, call getApplicationContext() here.
handler = new Handler();
}
#Override
protected void onHandleIntent(Intent intent) {
WakefulBroadcastReceiver.completeWakefulIntent(intent);
handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(MyTestService.this, "start", Toast.LENGTH_LONG).show();
int i = 0;
}
});
int i=0;
while(true){
i++;
// Do some work here
if(i>1000)
i=0;
}
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(MyTestService.this, "stop", Toast.LENGTH_SHORT).show();
}
}
I used while(true) in MyTestService for check that app is running in background, in project I will use sensors (this is pedometer application) then I want to put something like MyAlarmReceiver from tutorial to send data to the server several times a day.
try this
Manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.mkonuk.rebootapplication">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<service android:name=".MyService"/>
<receiver android:name=".MyBootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
MainActivity
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startService(new Intent(getBaseContext(),MyService.class));
}
}
MyService
public class MyService extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(getApplicationContext(),"Service started",Toast.LENGTH_LONG).show();
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(getApplicationContext(),"Service Destroyed",Toast.LENGTH_LONG).show();
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
MyBootReceiver
public class MyBootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent service = new Intent(context,MyService.class);
context.startService(service);
}
}
I have tested when application started service will be start , even if your application destroyed service will be started again.Even if reboot android device service will be started.
Second question :
if you will use sensor with service you need to register sensor listener and unregister sensor listener when service destroyed,oncreate method override sensor object and create sensor and sensor manager.In onstartCommand method register generated sensor listener sensor manager object ,unregister listener when service destroy
you can check this link
Accelemeter in android
if you want to send message from service to activity,you have to implement onbind() method ,activity need to bind on service check this link
bind activity on service using sensor
bind/unbind service
Hello I am a little new and looking for the some help, (It is not an answer) I coulndt add any other commentI was trying to execute a similar app, I followed what mithat show,then when I turn off my mobili it seems like it starts, but just when I put my cellphone password, it appears a system toast that says "app Stop", so i could t get it. Even when I sweep the app from 'Recent app" it says "app Stop"
I would like to run it for ever,
thanks
I have an android foreground service that is supposed to start running when the device boots up. At the boot the banner rolls by signaling that the service has started, however the banner does not stay in the notification bar after the initial notification runs buy. Additionally the service does not continue to run.Below is my manifest, broadcast receiver, and service.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.copyright.Going_Plaid"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED"
>
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
/>
<application
android:allowBackup="true" android:label="Going_Plaid"
android:icon="#mipmap/ic_launcher" android:theme="#style/AppTheme">
<receiver android:name="com.example.copyright.Going_Plaid.autostart">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
<activity
android:name="com.example.copyright.Going_Plaid.MainActivity"
android:label="Going_Plaid">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<service
android:name="com.example.copyright.Going_Plaid.Scan"
android:exported="false"
android:enabled="true"
/>
</application>
autostart.java:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class autostart extends BroadcastReceiver {
public void onReceive(Context arg0, Intent arg1){
Intent intent = new Intent(arg0, Scan.class);
arg0.startService(intent);
Log.v("autostart", "service should be started");
}
}
Scan.java:
public IBinder onBind(Intent mServiceIntent){return null;}
#Override
public void onCreate(){
startInForeground();
notificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
#Override
public int onStartCommand( Intent mServiceIntent,int flags, int startId) {
executorService.execute(new Runnable() {
Most of the code has been redacted because I did not think it was relevant. The service does run fine when started through the UI but runs into issues when starting from boot without the user manually starting it. If you need any other information I would be happy to add it. Thank you in advance for your assistance.
I want to install my widget to my home page after i drag and drop it, but when i do it, it says app can't get installed here is my code:
public class WidgetProvider extends AppWidgetProvider {
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
Intent receiver = new Intent(context, WidgetReceiver.class);
receiver.setAction("COM_FLASHLIGHT");
receiver.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, receiver, 0);
RemoteViews views = new RemoteViews(context.getPackageName(),
R.layout.widget_layout);
views.setOnClickPendingIntent(R.id.Button, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetIds, views);
}
}
And my provider info:
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="40dp"
android:minHeight="40dp"
android:updatePeriodMillis="86400000"
android:previewImage="#drawable/more"
android:initialLayout="#layout/widget_layout"
android:configure="com.flashlight.standroid.WidgetProvider"
android:resizeMode="horizontal|vertical"
android:label="Monitor Widget">
</appwidget-provider>
My Manifest:
<receiver
android:name=".WidgetProvider"
android:icon="#drawable/more"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="com.example.flash.ACTION_WIDGET_RECEIVER" />
<action android:name="android.appwidget.action.APPWIDGET_ENABLED" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/provider_info" />
</receiver>
<receiver
android:name="WidgetReceiver">
<intent-filter>
<action android:name="com.flashlight"></action>
</intent-filter>
</receiver>
Here i have gathered almost all the parts of code that i use to run/install.. my widget.Thanks in advance
Remove android:configure from your app widget metadata, or have it point to an activity to be used for configuring the app widget.
You can read more about configuration activities in the documentation.
change
android:configure="com.flashlight.standroid.FlashlightWidgetProvider"
with
android:configure="com.flashlight.standroid.WidgetProvider"
And make sure the Activity name is exactly wrote down on the android manifest.