Need to update TextView of a clock widget every second or every time the minute changes ..
I am calling the service from onReceive of my AppWidgetProvider :
private String action = "clock.beautiful.best.com.mmclock.TheService";
#Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
//UseThis
Log.e("h","R");
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.main_widget);
// Create a fresh intent
Intent serviceIntent = new Intent(context, TheService.class);
serviceIntent.setAction(action);
context.startService(serviceIntent);
ComponentName componentName = new ComponentName(context, TheService.class);
AppWidgetManager.getInstance(context).updateAppWidget(componentName, remoteViews);
}
What should i do to check for update in time and if there is a then update the 'time' TextView..
Service :
public class TheService extends Service {
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
Log.e("Service","created");
}
#Override
public void onDestroy() {
Log.e("Service","Destroy");
}
public void changeYexy (){
RemoteViews remoteViews = new RemoteViews(TheService.this.getPackageName(), R.layout.main_widget);
remoteViews.setTextViewText(R.id.dateTextView,"T");
}
#Override
public void onStart(Intent intent, int startid) {
Log.e("Service","start");
}
}
I don't want users to open the activity again and again to update , is there any way i can check and update the time from service or widget..
Any kind of is really really really appreciated
Instead of Using service you can use AlarmManager to update widget periodically
public class Alarm
{
public static void setAlarm(Context context, int interval)
{
AlarmManager am =( AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, yourWidget.class);
intent.setAction("WIDGET_UPDATE");
int[] ids = AppWidgetManager.getInstance(context)
.getAppWidgetIds(new ComponentName(context, yourWidget.class));
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, 0);
am.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + interval * 1000, pi);
}
public void cancelAlarm(Context context)
{
Intent intent = new Intent(context, Alarm.class);
PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(sender);
}
}
in this way the alram send a broadCast to widget with "WIDGET_UPDATE" as action after interval seconds.
Enable the alarm in onEnable method of your widget:
#Override
public void onEnabled(Context context) {
super.onEnabled(context);
Alarm.setAlarm(context, 1);
}
In the onReceive method of yourWidget update yourWidget and set the alarm for next time
#Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
if ("WIDGET_UPDATE".equals(intent.getAction())) {
int[] appWidgetIds = AppWidgetManager.getInstance(context)
.getAppWidgetIds(new ComponentName(context, yourWidget.class));
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
//set alarm for the next time
Alarm.setAlarm(context, 1);
//update your widget here
onUpdate(context, appWidgetManager, appWidgetIds);
}
}
Note : although it is possile to use setRepeating instead of setExact but for me it does not work properly
Related
I am using a foreground service in my application I need to stop this service from a button that is present on the notification itself without opening the activity.
My current code
This is my activity from where I am starting the service.
serviceIntent = new Intent(getApplicationContext(),BackgroundService.class);
serviceIntent.putExtra("ip",ipAdd);
serviceIntent.putExtra("token",token);
serviceIntent.putExtra("port",portNo);
serviceIntent.putExtra("resource",resourceId);
serviceIntent.putExtra("userName",username);
startService(serviceIntent);
ClosingBackGroundService.getMainActivityContext(MainActivity.this);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
stopService(serviceIntent);
}
});
I am using a class to show the button on the notification and trying to close the activity
public class ClosingBackGroundService extends BroadcastReceiver {
static Context mainActContext;
public static void getMainActivityContext(Context context){
mainActContext = context;
}
#Override
public void onReceive(Context context, Intent intent) {
mainActContext.stopService(MainActivity.serviceIntent);
Log.i("Service","closed");
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(broadcastReceiver, filter);
Intent notificationIntent = new Intent(this,LoginActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,0,notificationIntent,0);
Intent closingIntent = new Intent(this,ClosingBackGroundService.class);
PendingIntent actionIntent = PendingIntent.getBroadcast(this,0,closingIntent,PendingIntent.FLAG_UPDATE_CURRENT);
Notification notification = new NotificationCompat.Builder(this,CHANNEL_ID)
.setOngoing(true)
.setSmallIcon(R.drawable.logo)
.addAction(R.mipmap.ic_launcher,"Close Services",actionIntent)
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.setContentText("Processes Running In BackGround").build();
ipAdd = intent.getStringExtra("ip");
port = intent.getStringExtra("port");
token = intent.getStringExtra("token");
resourceId = intent.getIntExtra("resource",0);
username = intent.getStringExtra("userName");
runnableForGps.run();
runnableForSendingGpsData.run();
runnableForBluetooth.run();
runnableForsendingBTData.run();
startForeground(1,notification);
return START_STICKY;
}
When I press the button the notification disappears but the process keeps on working.
You don't need to create BroadCast to stop Service. Try this
private static final String ACTION_STOP_LISTEN = "action_stop_listen";
Intent intent = new Intent(this, ClosingBackGroundService.class);
intent.setAction(ACTION_STOP_LISTEN);
PendingIntent actionIntent = PendingIntent.getService(this, 123, intent, PendingIntent.FLAG_UPDATE_CURRENT);
addAction(R.mipmap.ic_launcher,"Close Services",actionIntent)
In onStartCommand check your Intent action
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null && ACTION_STOP_LISTEN.equals(intent.getAction())) {
stopForeground(true);
stopSelf();
return START_NOT_STICKY;
}
// your code
}
I have used this cancelAlarm method from another reputable answer on stack, and it isn't getting the job done, and I am out of ideas of why this isn't working.
I have an activity where one button will start an alarm that will go off every given interval. I then have another button that will cancel that alarm. Here are the buttons first:
start.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
setupAlarm(10);
}
});
stop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try{
cancelAlarm(ALARM_ID);
} catch(Exception e){
Toast.makeText(getApplicationContext(), "ERROR", Toast.LENGTH_SHORT).show();
}
}
});
And here are my setupAlarm and cancelAlarm methods:
private void setupAlarm(int seconds) {
AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
Intent i = new Intent(getBaseContext(), AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
MainActivity.this, ALARM_ID, i, PendingIntent.FLAG_UPDATE_CURRENT);
Calendar t = Calendar.getInstance();
t.setTimeInMillis(System.currentTimeMillis());
int interval = seconds*1000;
am.setRepeating(AlarmManager.RTC_WAKEUP, t.getTimeInMillis(), interval, pendingIntent);
MainActivity.this.finish();
}
private void cancelAlarm(int alarmId){
Intent i = new Intent(getBaseContext(), AlarmManager.class);
PendingIntent sender = PendingIntent.getBroadcast(MainActivity.this, alarmId, i, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.cancel(sender);
sender.cancel();
}
I remembered to make another alarm manager with the same ID, and call alarmManager.cancel(sender); on the PendingIntent but it doesn't seem to do anything, because my service will start back up anyway.
AlarmReciever class:
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent)
{
Context oAppContext = context.getApplicationContext();
if (oAppContext == null) {
oAppContext = context;
}
Intent serviceIntent = new Intent(oAppContext, MyService.class);
oAppContext.startService(serviceIntent);
}
}
MyService class:
public class MyService extends Service implements SensorEventListener{
private PowerManager.WakeLock wakeLock;
Sensor mSensor;
SensorManager mSensorManager;
String toastString = "";
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate(){
mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL);
PowerManager mgr = (PowerManager) getApplicationContext().getSystemService(Context.POWER_SERVICE);
wakeLock = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyWakeLock");
wakeLock.acquire();
Toast.makeText(this, "onCreate Successful", Toast.LENGTH_SHORT).show();
}
#Override
public int onStartCommand(Intent intent, int flags, int startid) {
Toast.makeText(this, "onStart Successful", Toast.LENGTH_SHORT).show();
return Service.START_STICKY;
}
#Override
public void onSensorChanged(SensorEvent event) {
//record some data from the accelerometer
quit();
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
private void quit(){
mSensorManager.unregisterListener(MyService.this);
wakeLock.release();
this.stopSelf();
}
}
And I keep on getting the toasts from my MyService class telling me that my onCreate and onStart were successfully instantiated, even after calling my cancelAlarm method.
Use same PendingIntent that you used while creating Alarm. Use AlarmReceiver.class instead of AlarmManager.class in your Intent:
Intent i = new Intent(getBaseContext(), AlarmReceiver.class);
Update cancelAlarm() method as below:
private void cancelAlarm(int alarmId){
Intent i = new Intent(getBaseContext(), AlarmReceiver.class);
PendingIntent sender = PendingIntent.getBroadcast(MainActivity.this, alarmId, i, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.cancel(sender);
sender.cancel();
}
Hope this will help~
I have this app which launches the function notifiy()in the NotificationService when ever device is started or when app is opened
my question is how I can make this notifiy() function be made on specific times daily for example at (12:00 AM, 3:00 AM) I searched for a while and all I saw is working with AlarmManager but I don't understand how to use it in my code
MainActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startService(new Intent(this,NotificationService.class));
BootReceiver
public class BootReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
context.startService(new Intent(context,NotificationService.class));
}
}
NotificationService
public class NotificationService extends Service {
private MediaPlayer mediaPlayer;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
notifiy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
try {
}catch (Exception e){
e.printStackTrace();
}
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
try {
}catch (Exception e){
e.printStackTrace();
}
Intent intent=new Intent("com.company.app");
intent.putExtra("yourvalue","torestore");
sendBroadcast(intent);
}
public void notifiy(){
IntentFilter intentFilter=new IntentFilter();
intentFilter.addAction("RSSPullService");
Intent mIntent=new Intent(Intent.ACTION_VIEW, Uri.parse(""));
PendingIntent pendingIntent=PendingIntent.getActivity(getBaseContext(),0,mIntent,Intent.FLAG_ACTIVITY_NEW_TASK);
Context context=getApplicationContext();
Notification.Builder builder;
builder=new Notification.Builder(context)
.setContentTitle(title)
.setContentText("")
.setContentIntent(pendingIntent)
.setDefaults(Notification.DEFAULT_SOUND)
.setAutoCancel(true)
.setSmallIcon(R.drawable.images);
Notification notification=builder.build();
NotificationManager notificationManager=(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(1,notification);
mediaPlayer = MediaPlayer.create(this, R.raw.msound);
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mediaPlayer.start();
}
});
}
}
1. If you want to set alarm after launching app then you can add below codes in your MainActivity's onCreate() method:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Schedule Date & time
Calendar target = Calendar.getInstance();
target.set(2017, 5, 3, 12, 0, 0);
// Intent
Intent mIntent = new Intent(getApplicationContext(), AlarmReceiver.class);
mIntent.putExtra("MSG_ID", "SOME MESSAGE");
// Pending broadcast intent
PendingIntent mPI = PendingIntent.getBroadcast(getApplicationContext(), 0, mIntent, PendingIntent.FLAG_UPDATE_CURRENT);
// Alarm manager
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
// Set alarm
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, target.getTimeInMillis(), AlarmManager.INTERVAL_DAY, mPI);
}
2. If you want to set alarm after boot completion, then you can add that code in BootReceiver's onReceive() method:
public class BootReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
// Schedule Date & time
Calendar target = Calendar.getInstance();
target.set(2017, 5, 3, 12, 0, 0);
// Intent
Intent mIntent = new Intent(getApplicationContext(), AlarmReceiver.class);
mIntent.putExtra("MSG_ID", "SOME MESSAGE");
// Pending broadcast intent
PendingIntent mPI = PendingIntent.getBroadcast(getApplicationContext(), 0, mIntent, PendingIntent.FLAG_UPDATE_CURRENT);
// Alarm manager
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
// Set alarm
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, target.getTimeInMillis(), AlarmManager.INTERVAL_DAY, mPI);
}
}
Here is AlarmReceiver class:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent)
{
context.startService(new Intent(context, NotificationService.class));
Log.d("AlarmReceiver", "Called ");
}
}
Declare AlarmReceiver class in AndroidManifest.xml:
<receiver
android:name="YOUR_PACKAGE.AlarmReceiver">
</receiver>
I am trying to create a simple android widget that shows and I want to use custom font in my application, can anyone help me?
this my code :
public class ExampleAppWidgetProvider extends AppWidgetProvider {
private static final String LOG_TAG = "ExampleWidget";
private static final DateFormat df = new SimpleDateFormat("hh:mm:ss");
/**
* Custom Intent name that is used by the AlarmManager to tell us to update
* the clock once per second.
*/
public static String CLOCK_WIDGET_UPDATE = "com.eightbitcloud.example.widget.8BITCLOCK_WIDGET_UPDATE";
#Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
if (CLOCK_WIDGET_UPDATE.equals(intent.getAction())) {
Log.d(LOG_TAG, "Clock update");
// Get the widget manager and ids for this widget provider, then
// call the shared
// clock update method.
ComponentName thisAppWidget = new ComponentName(
context.getPackageName(), getClass().getName());
AppWidgetManager appWidgetManager = AppWidgetManager
.getInstance(context);
int ids[] = appWidgetManager.getAppWidgetIds(thisAppWidget);
for (int appWidgetID : ids) {
updateAppWidget(context, appWidgetManager, appWidgetID);
}
}
}
private PendingIntent createClockTickIntent(Context context) {
Intent intent = new Intent(CLOCK_WIDGET_UPDATE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
return pendingIntent;
}
#Override
public void onDisabled(Context context) {
super.onDisabled(context);
Log.d(LOG_TAG, "Widget Provider disabled. Turning off timer");
AlarmManager alarmManager = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(createClockTickIntent(context));
}
#Override
public void onEnabled(Context context) {
super.onEnabled(context);
Log.d(LOG_TAG,
"Widget Provider enabled. Starting timer to update widget every second");
AlarmManager alarmManager = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, 1);
alarmManager.setRepeating(AlarmManager.RTC, calendar.getTimeInMillis(),
1000, createClockTickIntent(context));
}
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
final int N = appWidgetIds.length;
Log.d(LOG_TAG, "Updating Example Widgets.");
// 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, WidgetExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
intent, 0);
// Get the layout for the App Widget and attach an on-click listener
// to the button
RemoteViews views = new RemoteViews(context.getPackageName(),
R.layout.widget1);
views.setOnClickPendingIntent(R.id.button, pendingIntent);
// Tell the AppWidgetManager to perform an update on the current app
// widget
appWidgetManager.updateAppWidget(appWidgetId, views);
// Update The clock label using a shared method
updateAppWidget(context, appWidgetManager, appWidgetId);
}
}
public static void updateAppWidget(Context context,
AppWidgetManager appWidgetManager, int appWidgetId) {
String currentTime = df.format(new Date());
RemoteViews updateViews = new RemoteViews(context.getPackageName(),
R.layout.widget1);
updateViews.setTextViewText(R.id.widget1label, currentTime);
appWidgetManager.updateAppWidget(appWidgetId, updateViews);
}
}
If I have two widgets and I press on a button on the first one, the second widget updates itself. That is not the intention :) When debugging I noticed that the first widget the widgetid of te second used for updating
public class WidgetActivity extends AppWidgetProvider {
public static WidgetActivity Widget = null;
public static Context context;
public static AppWidgetManager appWidgetManager;
public static int appWidgetIds[];
public static String ACTION_OPEN_APP = "OpenApp";
private static int appWidgetId;
#Override
public void onUpdate( Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds ) {
if (null == context) context = WidgetActivity.context;
if (null == appWidgetManager) appWidgetManager = WidgetActivity.appWidgetManager;
if (null == appWidgetIds) appWidgetIds = WidgetActivity.appWidgetIds;
WidgetActivity.Widget = this;
WidgetActivity.context = context;
WidgetActivity.appWidgetManager = appWidgetManager;
WidgetActivity.appWidgetIds = appWidgetIds;
final int N = appWidgetIds.length;
for (int i=0; i<N; i++)
{
appWidgetId = appWidgetIds[i];
updateAppWidget(context,appWidgetManager, appWidgetId);
}
}
public void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
int appWidgetId) {
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget);
Intent intent = new Intent(context, UpdateService.class);
PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, 0);
Intent configIntent = new Intent(context, Main.class);
configIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent configPendingIntent = PendingIntent.getActivity(context, 0, configIntent, 0);
remoteViews.setOnClickPendingIntent(R.id.headlinesBox, configPendingIntent);
remoteViews.setOnClickPendingIntent(R.id.WidgetRefresh_btn, pendingIntent);
setHeadlines(appWidgetId);
// Tell the widget manager
appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
}
public static void setHeadlines(int appWidgetId)
{
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget);
ArrayList<String> newsItems = getRssItems("*****rss.php", appWidgetId);
if(newsItems.size() == 3)
{
remoteViews.setTextViewText(R.id.headline1, newsItems.get(0));
remoteViews.setTextViewText(R.id.headline2, newsItems.get(1));
remoteViews.setTextViewText(R.id.headline3, newsItems.get(2));
}
DateTime dateTime = new DateTime();
CharSequence text = dateTime.getTime();
remoteViews.setTextViewText(R.id.WidgetUpdateTime, text);
remoteViews.setViewVisibility(R.id.progressWidget, View.GONE);
remoteViews.setViewVisibility(R.id.WidgetRefresh_btn, View.VISIBLE);
appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
}
public static ArrayList<String> getRssItems(String feedUrl, int appWidgetId)
{
}
public static class UpdateService extends Service {
#Override
public void onStart(Intent intent, int startId) {
RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.widget);
remoteViews.setViewVisibility(R.id.WidgetRefresh_btn, View.GONE);
remoteViews.setViewVisibility(R.id.progressWidget, View.VISIBLE);
appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
WidgetActivity.Widget.onUpdate(context, appWidgetManager, appWidgetIds);
}
#Override
public IBinder onBind(Intent arg0) {
return null;
}
}
}
It is difficult to understand what you mean by:
When debugging I noticed that the first widget the widgetid of te second used for updating
But, I think I understand your general problem: your AppWidgets are not being updated correctly? After glancing at your code, it looks like your problem could be that appWidgetId is declared as static. Perhaps try removing that keyword.
Also, I don't see anywhere in your code a button.
EDIT
It looks like your appWidgetId is being overwritten. Here is my suggestion, take advantage of the AppWidgetProvider being a broadcast receiver and instead send a broadcast as a result of your PendingIntent button click. You will also have to make sure to pass the appWidgetId as an extra to ensure that the correct widget gets updated. Here is an example, should be in your updateAppWidget method:
Intent refreshAction = new Intent();
refreshAction.setAction(MY_CUSTOM_REFRESH_ACTION);
refreshAction.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
PendingIntent refreshPendingIntent.........
And then in the onReceive override:
#Override
public void onReceive(Context context, Intent intent) {
.....
Bundle extras = intent.getExtras();
int appWidgetId = extras.getExtra(AppWidgetManager.EXTRA_APPWIDGET_ID);
.....
}
And then you should be ready to go, updating the correct widget. One more caveat, make sure to read the documentation on BroadcastReceivers if you have not already. You will have to register to accept MY_CUSTOM_REFRESH_ACTION within the WidgetActivity element in your AndroidManifest.