I have a widget with 1 image view and 1 text view.
I want to change image on click. Consider following code doesn't catch touch event
package com.sigrlami.rixvpn.widget;
import java.util.Random;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.RemoteViews;
import com.sigrlami.rixvpn.R;
public class VpnWidgetProvider extends AppWidgetProvider {
private boolean currentStatus = false;
// log tag
private static final String LOG = "com.sigrlami.rixvpn.widget.VpnWidgetProvider";
//public static final String CLICK = "com.sigrlami.rixvpn.CLICK";
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
// Get all ids
ComponentName thisWidget = new ComponentName(context, VpnWidgetProvider.class);
int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
for (int widgetId : allWidgetIds) {
// Create some random data
int number = (new Random().nextInt(100));
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.vpn_widget);
Log.w("WidgetExample", String.valueOf(number));
// Set the text
remoteViews.setTextViewText(R.id.layout_vpn_widget_tv_Check, String.valueOf(number));
// Register an onClickListener
Intent intent = new Intent(context, VpnWidgetProvider.class);
intent.setAction(appWidgetManager.ACTION_APPWIDGET_UPDATE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
remoteViews.setOnClickPendingIntent(R.id.layout_vpn_widget_iv_Check, pendingIntent);
if (currentStatus = false) {
remoteViews.setImageViewResource(R.id.layout_vpn_widget_iv_Check, R.drawable.on);
} else {
remoteViews.setImageViewResource(R.id.layout_vpn_widget_iv_Check, R.drawable.off);
}
appWidgetManager.updateAppWidget(widgetId, remoteViews);
}
}
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)) {
if (currentStatus == false) {
currentStatus = true;
} else {
currentStatus = false;
}
}
super.onReceive(context, intent);
}
}
Looking to this part through debugger shows nothing strange, but when I change to getActivity() it shows that I'm trying to start a activity that does not exist. I see that something is going on, but this is useless to me.
// Register an onClickListener
Intent intent = new Intent(context, VpnWidgetProvider.class);
intent.setAction(appWidgetManager.ACTION_APPWIDGET_UPDATE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
remoteViews.setOnClickPendingIntent(R.id.layout_vpn_widget_iv_Check, pendingIntent);
But it works 1 time when app deployed to device.
Any suggestions what I have done wrong?
For handling click in AppWidgetProvider you need to use custom broadcast reciver as:
<receiver android:name="VpnWidgetProvider"
android:label="#string/widget_title" android:exported="false" android:icon="#drawable/volume">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="com.xxxx.xxxx.VpnWidgetProvider.ACTION_WIDGET_REFRESH"/>
<action android:name="android.appwidget.action.APPWIDGET_DELETED"/>
<action android:name="android.media.RINGER_MODE_CHANGED"/>
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="#xml/widget_info" />
and in AppWidgetProvider class:
public class VpnWidgetProvider extends AppWidgetProvider {
public static String ACTION_WIDGET_REFRESH = "ActionReceiverRefresh";
//your code here...
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
//you code here...
Intent intent = new Intent(context, VpnWidgetProvider.class);
intent.setAction(appWidgetManager.ACTION_WIDGET_REFRESH);//get action here
//you code here...
see this full working example for handling onclick on home Screen AppWidget:
Silenttoggle Home Screen Widget
Related
I need a button in my Notification, however everything i find online is not working. I need it to cancel playing an alarm that will go off at a designated time. Can anyone link me some articles to read or tell me what code i should use in order to get this to work.
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.media.RingtoneManager;
import android.os.Build;
import android.util.Log;
import android.widget.Toast;
import androidx.core.app.NotificationCompat;
import com.example.oceansscheduler.MainActivity;
import com.example.oceansscheduler.R;
public class AlarmReceiver extends BroadcastReceiver {
public void showNotification(Context context, String title, String message, Intent intent, int reqCode) {
PendingIntent pendingIntent = PendingIntent.getActivity(context, reqCode, intent, PendingIntent.FLAG_ONE_SHOT);
String CHANNEL_ID = "channel_name";// The id of the channel.
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_baseline_alarm_24)
.setContentTitle(title)
.setStyle(new NotificationCompat.BigTextStyle())
.setPriority(NotificationCompat.PRIORITY_MAX)
.setContentText(message)
.setAutoCancel(true)
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setContentIntent(pendingIntent);
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = "Channel Name";// The user-visible name of the channel.
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel mChannel = new NotificationChannel(CHANNEL_ID, name, importance);
notificationManager.createNotificationChannel(mChannel);
}
notificationManager.notify(reqCode, notificationBuilder.build()); // 0 is the request code, it should be unique id
Log.d("showNotification", "showNotification: " + reqCode);
}
#Override
public void onReceive(Context context, Intent intent) {
SQLiteDatabase db = context.openOrCreateDatabase("NotificationDatabase", android.content.Context.MODE_PRIVATE, null);
Cursor data = db.rawQuery("SELECT * FROM PersonalNotif", null);
Log.d("Count", String.valueOf(data.getCount()));
if (data.getCount() > 0) {
data.moveToFirst();
String NameOfNotif = (data.getString(0));
Toast.makeText(context, NameOfNotif, Toast.LENGTH_LONG).show();
int reqCode = 1;
Intent intentNotif = new Intent(context, MainActivity.class);
showNotification(context, NameOfNotif, "Your Reminder is going off!", intentNotif, reqCode);
}
}
};
To add a button in Your notification, You need to use addAction function.
It requires an Action object which needs:
an icon (oddly),
a title,
a PendingIntent
The PendingItent can encapuslate an Intent that can be a Service that will be delegated to cancel playing the alarm or a Receiver that will do it.
Let's stick with a receiver. We can create one - CancelAlarmReceiver:
public class CancelAlarmReceiver extends BroadcastReceiver {
public static String ACTION_CANCEL = "actionCancelAlarm";
public CancelAlarmReceiver() {}
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION_CANCEL)) {
// Here You will cancel the alarm.
}
}
}
Remember to register it in the Manifest:
<receiver
android:name=".CancelAlarmReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="com.your.app.CancelAlarmReceiver.ACTION_CANCEL" />
</intent-filter>
</receiver>
Later on, when creating a notification with a builder, You will have to provide an action leading to our Receiver:
Intent cancelIntent = new Intent(this, CancelAlarmReceiver.class);
cancelIntent.setAction(ACTION_CANCEL);
PendingIntent cancelPendingIntent =
PendingIntent.getBroadcast(this, NOTIFICATION_ID,
cancelIntent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.addAction(
new Notification.Action(
R.drawable.ic_alarm_cancel,
getString(R.string.cancel_alarm),
cancelPendingIntent
)
);
This should make sure that a button will appear by Your notification and it will trigger the receiver and disable the alarm (or whatever You will make it to do).
I have an application which starts a service when the widget is tapped.
This is the class for the widget:
public class PlayWidget extends AppWidgetProvider {
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
for (int i = 0; i < appWidgetIds.length; i++) {
int currentWidgetId = appWidgetIds[i];
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.playwidget);
views.setTextViewText(R.id.bLevelText, "My widget");
Intent intent = new Intent(context, PlayService.class);
intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
PendingIntent pending = PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
views.setOnClickPendingIntent(R.id.imageButton11, pending);
appWidgetManager.updateAppWidget(currentWidgetId, views);
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds[i], R.id.imageButton11);
}
}
}
This is the manifest declaration for the Widget:
<receiver
android:name=".widget.PlayWidget"
android:icon="#drawable/play">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/playwidget_info" />
</receiver>
This is the manifest declaration for the Service:
<service android:name=".widget.PlayService"/>
The problem is that on Android 11, when the app is killed and i press the widget, the Service won't start anymore. Anyone has an idea on how can i fix this issue?
I have found an workaround for this issue, by calling a BroadcastReceiver from the OnUpdate function, and then starting the Service from the BroadcastReceiver :
Intent intent = new Intent();
intent.setAction(START_SERVICE);
intent.setClassName(StartServiceReceiver.class.getPackage().getName(), StartServiceReceiver.class.getName());
PendingIntent pending = PendingIntent.getBroadcast(context, 0, intent, 0);
views.setOnClickPendingIntent(R.id.imageButton11, pending);
This is the code for the BroadcastReceiver:
public class StartServiceReceiver extends BroadcastReceiver {
public static final String START_SERVICE= "start_service";
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(START_SERVICE)) {
context.startService(new Intent(context, PlayService.class));
}
}
}
And the manifest declaration for the BroadcastReceiver:
<receiver android:name=".StartServiceReceiver" android:label="#string/app_name"/>
I am new to android studio. I need to create a note application with a reminder function. I decided to do this through the alarmmanager, but it only works when the application is open. Is it realistic to do this only through services?
I noticed that in the google keep application, when creating a reminder, a new service is created. How to do this?
Part of the code from the activity:
public void alarm(Calendar c) {
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, AlertReceiver.class);
intent.putExtra("title",editTask.getText().toString());
PendingIntent pen = PendingIntent.getBroadcast(this, 1, intent, 0);
alarmManager.set(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(),pen);
AlertReciver.java
package denchic45.myapp.appmy;
import android.content.BroadcastReceiver;
import android.content.Intent; import android.widget.Toast;
import android.content.Context;
public class AlertReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
intent = new Intent(context, Services.class);
context.startService(intent);
Toast.makeText(context, "alarm", Toast.LENGTH_SHORT).show();
} }
Services.java
package denchic45.myapp.appmy;
import android.app.IntentService;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
public class Services extends IntentService {
public Services() {
super("public services");
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
protected void onHandleIntent(#Nullable Intent intent) {
Context context = getApplicationContext();
Toast.makeText(context, "WORK", Toast.LENGTH_SHORT).show();
final String CHANNEL_ID = "1";
if(Build.VERSION.SDK_INT = Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(CHANNEL_ID,"001",
NotificationManager.IMPORTANCE_DEFAULT);
channel.setDescription("description");
NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
manager.createNotificationChannel(channel);
NotificationCompat.Builder notification = new NotificationCompat.Builder(context, CHANNEL_ID)
.setContentTitle("dd")
.setSmallIcon(R.mipmap.ic_launcher);
notification.build();
NotificationManagerCompat managerCompat = NotificationManagerCompat.from(context);
managerCompat.notify(1,notification.build());
} else {
NotificationCompat.Builder notification = new NotificationCompat.Builder(context, CHANNEL_ID)
.setContentTitle("dd")
.setSmallIcon(R.drawable.note)
.setChannelId(CHANNEL_ID);
notification.build();
NotificationManagerCompat managerCompat = NotificationManagerCompat.from(context);
managerCompat.notify(1,notification.build());
}
} }
Part of the code from the manifest:
<receiver android:name=".AlertReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<service android:name=".Services"/>
I am learning how to build home screen widget in Android. This code is for an app widget to toggle RingerMode from NORMAL to SILENT and vice-versa.
This works fine but I need a full in-sight of logical flow (i.e which gets initiated when, goes where, does what, dies when) of all the intents in this.
Please help me understand this topic clearer.
package com.dummies.android.silentmodetoggle;
import android.app.Activity;
import android.app.IntentService;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.util.Log;
import android.widget.RemoteViews;
public class AppWidget extends AppWidgetProvider {
public static String tag ="SilentModeToggleWidget";
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Log.d(tag, "onReceive() first line");
if(intent.getAction()==null)
{
//Do Something
Log.d(tag, "before startService()");
context.startService(new Intent(context, ToggleService.class));
}
else{
super.onReceive(context, intent);
}
}
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
// Do something in specified intervals
context.startService(new Intent(context, ToggleService.class));
}
public static class ToggleService extends IntentService{
public ToggleService(){
super("AppWidget$ToggleService");
Log.d(tag, "In ToggleService construcor");
}
#Override
protected void onHandleIntent(Intent arg0) {
Log.d(tag, "In ToggleService > onHandleIntent");
// TODO Auto-generated method stub
ComponentName cn = new ComponentName(this, AppWidget.class);
AppWidgetManager mgr = AppWidgetManager.getInstance(this);
mgr.updateAppWidget(cn, buildUpdate(this));
}
private RemoteViews buildUpdate(Context context){
RemoteViews updateViews = new RemoteViews(context.getPackageName(), R.layout.widget);
AudioManager audioManager = (AudioManager)context.getSystemService(Activity.AUDIO_SERVICE);
if(audioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT){
updateViews.setImageViewResource(R.id.phoneState, R.drawable.phone_on);
audioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
}
else{
updateViews.setImageViewResource(R.id.phoneState, R.drawable.phone_silent);
audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
}
Intent i = new Intent(this, AppWidget.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
updateViews.setOnClickPendingIntent(R.id.phoneState, pi);
return updateViews;
}
}
}
still not sure on what are u asking, but I'll try to answer, if not what u want, please explain in a different way.
Intent are usually started immediatly. You create an Intent can start it by calling startService or startActivity, so for example:
context.startService(new Intent(context, ToggleService.class));
on both times you wrote the above code, the service ToggleService is immediatly started.
PendingIntent on the other hand are saved to be started at later time, so for example
updateViews.setOnClickPendingIntent(R.id.phoneState, pi);
on the above line, the AppWidget Broadcast is started when the user clicks on R.id.phoneState in your HomeScreen AppWidget.
Each PendingIntent is stored in the system with a certain ID, this ID is the requestCode parameter (you used zero on your code)... that means, that if you create a different PendingIntent with the same ID it will override it, meaning a different action will be started when the user clicks on R.id.phoneState
I am trying to get SMS broadcasted to few mobile numbers every time the sim card is changed. Unfortunately, it doesn't work when I try it on my device. Can someone identify the issue in my following code please. The onBoot permissions are all added.
public class SendSmsOnTheft extends BroadcastReceiver
{
static void sendSMS(String destinationAddress, String text, Context context)
{
Intent intent = new Intent(context, SendSmsOnTheft.class);
PendingIntent pendingintent = PendingIntent.getActivity(context, 0, intent, 0);
SmsManager.getDefault().sendTextMessage(destinationAddress, null, text, pendingintent, null);
}
public void onReceive(Context context, Intent intent)
{
if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction()))
{
Log.d("VogueTools", "Got the Boot Event>>>");
TelephonyManager telephonymanager = (TelephonyManager)context.getSystemService("phone");
SharedPreferences sharedpreferences = context.getSharedPreferences("file", 0);
String number1 = sharedpreferences.getString("no1", "");
String number2 = sharedpreferences.getString("no2", "");
String number3 = sharedpreferences.getString("no3", "");
String number4 = sharedpreferences.getString("no4", "");
String extra = ("Mobile of IMEI NO: ")+
telephonymanager.getDeviceId()+
" is currently used" +
" by the SIM card service provider:" +
telephonymanager.getSimOperatorName().toString();
String simno = sharedpreferences.getString("simno", "");
String serialno = ((TelephonyManager)context.getSystemService("phone")).getSimSerialNumber();
if (number1.length() == 0)
{
System.exit(0);
}
if (simno.equals(serialno))
{
sendSMS(number1, extra, context);
sendSMS(number2, extra, context);
sendSMS(number3, extra, context);
sendSMS(number4, extra, context);
}
}
System.exit(0);
}
}
Here is the code that I used in my app for the same purpose:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.telephony.TelephonyManager;
import android.telephony.gsm.SmsManager;
import android.util.Log;
import android.widget.Toast;
public class ListeningToBoot extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
// TODO Auto-generated method stub
if(intent.getAction().equals("android.intent.action.BOOT_COMPLETED"))
{
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
String urphone = tm.getLine1Number();
Log.v("Uphone","is "+urphone);
Toast.makeText(context, "MDN:"+urphone, Toast.LENGTH_SHORT).show();
SharedPreferences prefs = context.getSharedPreferences("MySimPreferences", Context.MODE_PRIVATE);
String mobile_No=prefs.getString("MDN", "un-known");
Log.v("from shared pref","MDN"+mobile_No);
String imei=prefs.getString("IMEI", "un-known");
Log.v("from shared pref","IMEI"+imei);
if(urphone.equals(mobile_No))
{
Log.v("MDN is same","shoudl do nothing");
Toast.makeText(context, "MDN no change", Toast.LENGTH_LONG).show();
}
else
{
Log.v("MDN is not same","send a message to someone");
SharedPreferences prefs_names = context.getSharedPreferences("MyPreferences", Context.MODE_PRIVATE);
String number_to_send=prefs_names.getString("Moblie_Number", "un-known");
Toast.makeText(context, "MDN changed", Toast.LENGTH_LONG).show();
String message_to_send="Your mobile number chagned:\nNew Number: "+urphone+"\nIMEI: "+imei;
SmsManager.getDefault().sendTextMessage(number_to_send, null, message_to_send, null,null);
}
}
}
}
Hope this helps.
Edit: Make sure you have given all the required permissions in manifest file.
I think we need a little more information in order to help you. Anyway, have you registered the receiver properly? You must have been something like this under application:
<receiver
android:name=".SendSmsOnTheft"
android:enabled="true"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
With permissions:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.SEND_SMS" />