Recently I have been interested in Android Development and a friend gave me the book "Android Application Development for Dummies". In the book, there is a example app entitled Silent Toggle Mode. Later on there it teaches you to make a home screen widget for the app. I have typed in everything from the book exactly but it still gives me an error notifying me that the onReceive() method is never called. Here is the code:
package com.example.myapplication;
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.widget.RemoteViews;
public class AppWidget extends AppWidgetProvider {
#Override
public void onRecieve(Context context, Intent intent) {
if(intent.getAction()==null) {
context.startService(new Intent(context, ToggleService.class));
} else {
super.onReceive(context, intent);
}
}
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
context.startService(new Intent(context, ToggleService.class));
}
public static class ToggleService extends IntentService {
public ToggleService() {
super("AppWidget$ToggleService");
}
#Override
protected void onHandleIntent(Intent intent) {
ComponentName me=new ComponentName(this, AppWidget.class);
AppWidgetManager mgr=AppWidgetManager.getInstance(this);
mgr.updateAppWidget(me, 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_state_normal);
audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
} else {
updateViews.setImageViewResource(R.id.phoneState,R.drawable.phone_state_silent);
audioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
}
Intent i=new Intent(this, AppWidget.class);
PendingIntent pi=PendingIntent.getBroadcast(context, 0, i, 0);
updateViews.setOnClickPendingIntent(R.id.phoneState, pi);
return updateViews;
}
}
}
You have a typo, it's onReceive() and not onRecieve(). Write it like this:
public void onReceive(Context context, Intent intent)
This is a good example of why we should always use the #Override annotation, it simplifies finding bugs such as this one.
Related
In my app(java) I am getting values from two different crypto Exchange. Then doing some calculation and getting output values. Values are refreshing every second. Now I want to set alert/notification whenever output values is greater than specific value. I want this whenever app is closed or running. How to do that because I am not able to do that when app is closed? Thanks.
You have to use Foreground Service to enable notification even when app is closed .
According to AndroidDevelopers,
Foreground services perform operations that are noticeable to the
user. Each foreground service must show a status bar notification that
has a priority of PRIORITY_LOW or higher. That way, users are actively
aware that your app is performing a task in the foreground and is
consuming system resources.
https://developer.android.com/guide/components/foreground-services
Example of code from Programmer'sWorld, to create foreground services and notification in your Android App
package com.example.myserviceclass;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.os.IBinder;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;
public class MyService extends Service {
private Integer alarmHour;
private Integer alarmMinute;
private Ringtone ringtone;
private Timer t = new Timer();
private static final String CHANNEL_ID = “MyNotificationChannelID”;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
alarmHour = intent.getIntExtra(“alarmHour”, 0);
alarmMinute = intent.getIntExtra(“alarmMinute”, 0);
ringtone = RingtoneManager.getRingtone(getApplicationContext(), RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE));
try {
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID )
.setContentTitle(“My Alarm clock”)
.setContentText(“Alarm time – ” + alarmHour.toString() + ” : ” + alarmMinute.toString())
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentIntent(pendingIntent)
.build();
startForeground(1, notification);
NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ID, “My Alarm clock Service”, NotificationManager.IMPORTANCE_DEFAULT);
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(notificationChannel);
}
catch (Exception e){
e.printStackTrace();
}
t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
if (Calendar.getInstance().getTime().getHours() == alarmHour &&
Calendar.getInstance().getTime().getMinutes() == alarmMinute){
ringtone.play();
}
else {
ringtone.stop();
}
}
}, 0, 2000);
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
ringtone.stop();
t.cancel();
super.onDestroy();
}
}
package com.example.myserviceclass;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.widget.TimePicker;
public class MainActivity extends AppCompatActivity {
private TimePicker timePicker;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.FOREGROUND_SERVICE}, PackageManager.PERMISSION_GRANTED);
timePicker = findViewById(R.id.timPicker);
final Intent intent = new Intent(this, MyService.class);
ServiceCaller(intent);
timePicker.setOnTimeChangedListener(new TimePicker.OnTimeChangedListener() {
#Override
public void onTimeChanged(TimePicker timePicker, int i, int i1) {
ServiceCaller(intent);
}
});
}
private void ServiceCaller(Intent intent){
stopService(intent);
Integer alarmHour = timePicker.getCurrentHour();
Integer alarmMinute = timePicker.getCurrentMinute();
intent.putExtra(“alarmHour”, alarmHour);
intent.putExtra(“alarmMinute”, alarmMinute);
startService(intent);
}
}
<?xml version=”1.0″ encoding=”utf-8″?>
<manifest xmlns:android=”http://schemas.android.com/apk/res/android”
package=”com.example.myserviceclass”>
<uses-permission android:name=”android.permission.FOREGROUND_SERVICE”/>
<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”>
<service android:name=”.MyService”/>
<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>
You can do with Notification setting.
first go in setting,
then in notification setting ,
on notification for your app.
Thank you
For this purpose, you can create a foreground service running. This way, you'll be able to notify the user even after he has exited out from the App.
Reference : https://developer.android.com/guide/components/foreground-services?authuser=1
In my MainActivity XML file, I have an EditText which id is editsearch. I have a service class for listening to the clipboard text and open my app. Everything is happening fine but I can't set the text to my editsearch when my app opens from service class.
findViewById method is not work in the onStartCommand method of my service. I have also tried defining my editsearch EditText as a static property in my MainActivity class but not getting my expected result.
Here is my service class
package com.learn24bd.ad;
import android.app.Service;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;
public class MyServiceReceiver extends Service {
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("MySerivce","Service Started");
final ClipboardManager clipboard = (ClipboardManager) this.getSystemService(Context.CLIPBOARD_SERVICE);
clipboard.addPrimaryClipChangedListener(new ClipboardManager.OnPrimaryClipChangedListener() {
public void onPrimaryClipChanged() {
String copiedText = clipboard.getText().toString();
Log.i("Copied",copiedText);
/* here i want to setText to my editsearch
also tried with static property
MainActivity.editsearch.setText(copiedText);
*/
Intent i = new Intent();
i.setClass(getApplicationContext(), MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
}
});
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDestroy() {
super.onDestroy();
}
}
Services aren't suitable for dealing with UI.
Instead, in your case, you should pass the clipboard content for the MainActivity class to handle. For that, pass it as an intent extra:
Intent i = new Intent();
i.setClass(getApplicationContext(), MainActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.putExtra("clipboard_text", copiedText)
startActivity(i);
And receive and handle the text in your activity:
String clipboardText = getIntent().getStringExtra("clipboard_text");
Then you can set the text to your EditText:
editText.setText(clipboardText)
My app listens to BOOT_COMPLETED to start.
<receiver android:name=".BootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</receiver>
But if my app crashes, how could I get it to automatically restart?
BOOT_COMPLETED is not a sticky intent.
To get Answer of your question is very simple. In that case you need to use Thread.setDefaultUncaughtExceptionHandler(). It will always enter in uncaughtException() in case your application crashed.For Check Full Tutorial Here
public class YourApplication extends Application {
private static Context mContext;
public static YourApplication instace;
#Override
public void onCreate() {
super.onCreate();
mContext = getApplicationContext();
instace = this;
}
#Override
public Context getApplicationContext() {
return super.getApplicationContext();
}
public static YourApplication getIntance() {
return instace;
}
}
DefaultExceptionHandler.java
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.lang.Thread.UncaughtExceptionHandler;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Environment;
import android.util.Log;
/**
* This custom class is used to handle exception.
*
* #author Chintan Rathod (http://www.chintanrathod.com)
*/
public class DefaultExceptionHandler implements UncaughtExceptionHandler {
private UncaughtExceptionHandler defaultUEH;
Activity activity;
public DefaultExceptionHandler(Activity activity) {
this.activity = activity;
}
#Override
public void uncaughtException(Thread thread, Throwable ex) {
try {
Intent intent = new Intent(activity, RelaunchActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_CLEAR_TASK
| Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(
YourApplication.getInstance().getBaseContext(), 0, intent, intent.getFlags());
//Following code will restart your application after 2 seconds
AlarmManager mgr = (AlarmManager) YourApplication.getInstance().getBaseContext()
.getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1000,
pendingIntent);
//This will finish your activity manually
activity.finish();
//This will stop your application and take out from it.
System.exit(2);
} catch (IOException e) {
e.printStackTrace();
}
}
}
I have an Alarmmanager that is repeatedly calling an AlarmReceiver. The AlarmReceiver in turn calls an activity (com.example.testapp.Activity). My problem is that after few calls the UI of my main activity is displayed again, which should not be the case. What can be done to prevent the UI from popping up?
I already tried to set (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_NO_ANIMATION) in the AlarmReceiver. My main activity has android:theme="#android:style/Theme.NoDisplay in the manifest.
I only want the UI of the main activity to be displayed when the user clicks the icon for starting the app. (Then the user clicks the start button of the main activity and from there on everything should run without UI).
Here is the AlarmReceiver code:
package com.example.testapp;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
try {
Toast.makeText(context, "I'm running", Toast.LENGTH_SHORT).show();
//start activity
Intent i = new Intent();
i.setClassName("com.example.testapp", "com.example.testapp.Activity");
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Here is the activity code:
package com.example.testapp;
import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.database.Cursor;
import android.provider.Browser;
import android.content.Intent;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class Activity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// a lot of code
Here is the main activity:
package com.example.testapp;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
findViewById(R.id.startAlarm).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "Alarm begin", Toast.LENGTH_SHORT).show();
// instantiate AlarmService.java
Intent intent = new Intent(MyActivity.this, AlarmService.class);
// start service
startService(intent);
}
});
findViewById(R.id.stopAlarm).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
PendingIntent pendingIntent;
/* Retrieve a PendingIntent that will perform a broadcast */
Intent alarmIntent = new Intent(MainActivity.this, AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, alarmIntent, 0);
AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
manager.cancel(pendingIntent);
Toast.makeText(MainActivity.this, "Alarm Canceled", Toast.LENGTH_SHORT).show();
}
});
}
}
Here is the code of the AlarmManager:
new Thread(new Runnable() {
#Override
public void run() {
{
PendingIntent pendingIntent;
/* Retrieve a PendingIntent that will perform a broadcast */
Intent alarmIntent = new Intent(AlarmService.this, AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(AlarmService.this, 0, alarmIntent, 0);
AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
int interval = 10000;
manager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), interval, pendingIntent);
} catch (Exception e) {
e.printStackTrace();
}
In my app, I've got a BroadcastReceiver, which is called by an AlarmManager. That BroadcastReceiver calls CommonsWare's WakefulIntentservice.
I tested this on my phone, and it appeared that sometimes, my BroadcastReceiver isn't called at all. I'm really confused about what it could be. My BroadcastReceiver and WakefulIntentservice are registerd in the manifest.
This is my code:
In AlarmActivity:
Calendar cal = Calendar.getInstance();
cal.add(Calendar.SECOND, 2);
Intent intent = new Intent(this, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), savedIntervalAutomaticMilisInt, pendingIntent);
Toast.makeText(this, "Saved", Toast.LENGTH_LONG).show();
finish();
AlarmReceiver:
package com.something.app;
import com.commonsware.cwac.wakeful.WakefulIntentService;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent i = new Intent(context, AlarmService.class);
WakefulIntentService.sendWakefulWork(context, i);
}
}
And AlarmService:
package com.something.app;
import android.app.PendingIntent;
import android.content.Intent;
import com.commonsware.cwac.wakeful.WakefulIntentService;
public class AlarmService extends WakefulIntentService {
public AlarmService() {
super("AlarmService");
}
#Override
protected void doWakefulWork(Intent arg0) {
//A looooooooot of stuff
}
Does anyone know why the BroadcastReceiver sometimes isn't called?
EDIT: I heard about setting a BroadcastReceiver which receives onBootCompleted. Is that required?
So, that's the problem: If the device reboots, it sometimes clears the alarm, so you have to reset them in a BroadcastReceiver which receives onBootCompleted