why does my service go inside the timertask loop? - android

I've tried to make an app that opens up a service, that changes the wallpaper on your phone every 5 hours.
For testing purposes I've only changed the timer for 1 minute just to see if it works (because when it's on 5 hours it doesn't work),
and indeed it changes the wallpaper every single minute. Even when I close my app and the service is closed
I have a statement to restart it so that works.
Unfortunately when the phone turns black (timeout for the screen). and I turn it back on it's like it stuck up all the time. It needed to go inside the listener while the phone was suspended, so it goes inside the timerTask like, 10 times in a row immediately (or the times it was offline..and it should have gone inside). In other words if I put the phone on rest for 10 minutes and then turn it back on, it will just change my wallpaper 10 times in a row.
So that's one problem. The other one is that if I change the timer for 5 hours it doesn't change the wallpaper at all.
Can someone help me or know why this is happening to me ?
this is my code >
my service >
package com.greenroad.candidate.mywallpaperchanger;
import android.app.Service;
import android.app.WallpaperManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.WindowManager;
import android.widget.Toast;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
/**
* Created by pitsponet on 31/08/2015.
*/
public class myService extends Service {
int oneSecond = 1000;
int oneMinute = oneSecond*60;
int oneHour = oneMinute*60;
int timerDeley = oneMinute;
private Timer timer;
//this is the tast or the reciver the timer will go into every time it has being called
private TimerTask timerTask = new TimerTask() {
#Override
public void run() {
//shows a toast saying timer listener has entered
Handler mainHandler = new Handler(getApplicationContext().getMainLooper());
mainHandler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), "timer listener Entered", Toast.LENGTH_LONG).show();
}
});
//gets the picture modifire to know what picture to choose to change the wallpaper to
// Access the default SharedPreferences
SharedPreferences pref = getApplicationContext().getSharedPreferences("myGlobalPrefTable", MODE_PRIVATE);
SharedPreferences.Editor editor = pref.edit();
Integer pictureModifireInt = pref.getInt("pictureModifire", 0);
//updates teh picture modifire by one
pictureModifireInt++;
/////holds a list with all the images that are avilable to change
int displayPicture = R.drawable.captain;
ArrayList<Integer> pictureNames = new ArrayList<>();
pictureNames.add(R.drawable.captain);
pictureNames.add(R.drawable.flash);
pictureNames.add(R.drawable.superman);
pictureNames.add(R.drawable.thor);
pictureNames.add(R.drawable.wonder);
pictureNames.add(R.drawable.a);
pictureNames.add(R.drawable.b);
pictureNames.add(R.drawable.c);
pictureNames.add(R.drawable.d);
pictureNames.add(R.drawable.e);
pictureNames.add(R.drawable.f);
pictureNames.add(R.drawable.g);
pictureNames.add(R.drawable.h);
pictureNames.add(R.drawable.i);
pictureNames.add(R.drawable.j);
pictureNames.add(R.drawable.k);
pictureNames.add(R.drawable.l);
pictureNames.add(R.drawable.m);
pictureNames.add(R.drawable.n);
pictureNames.add(R.drawable.o);
//logs the stored prefrence and select the correct image at place > picture modifire
Log.d("myLog", "storedPreference: " + pictureModifireInt);
displayPicture = pictureNames.get(pictureModifireInt-1);
//stores the picture modifire back in the shared prefrences or initlizes it if it reached the last image
if(pictureModifireInt > 19){
// Edit the saved preferences
Log.d("myLog", "putting in pictureModifire : : " + 0);
editor.putInt("pictureModifire", 0);
editor.commit();
} else {
Log.d("myLog", "putting in pictureModifire : : " + pictureModifireInt);
editor.putInt("pictureModifire", pictureModifireInt);
editor.commit();
}
//most important part of the code
//gets the dimentions of the phones screen and changes the wallpaper
//it has to get the dimentions so that the wallpaper will be in full screen
//maybe he can't do this part when he is in suspend mode ?
WindowManager wm= (WindowManager) getSystemService(MainActivity.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();
Bitmap bmap2 = BitmapFactory.decodeResource(getResources(), displayPicture);
Bitmap bitmap = Bitmap.createScaledBitmap(bmap2, width, height, true);
WallpaperManager wallpaperManager = WallpaperManager.getInstance(getApplicationContext());
try {
wallpaperManager.setBitmap(bitmap);
} catch (IOException e) {
e.printStackTrace();
}
//just shoes a post to let knnow what wallpaper has been changed, and that the walpaper indeed changed
mainHandler = new Handler(getApplicationContext().getMainLooper());
final Integer finalPictureModifireInt = pictureModifireInt-1;
mainHandler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), "wallpaper changed to : "+ finalPictureModifireInt+" and started a new timer", Toast.LENGTH_LONG).show();
}
});
}
};
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
//show a toast to indicae that a new service was created
Toast.makeText(getApplicationContext(), "a new service created",
Toast.LENGTH_LONG).show();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("MyLog", "a new service started");
final Handler mainHandler = new Handler(getApplicationContext().getMainLooper());
mainHandler.post(new Runnable() {
#Override
public void run() {
//show a toast to indicae that a new service was started
Toast.makeText(getApplicationContext(), "serviceStarterd", Toast.LENGTH_LONG).show();
// Access the default SharedPreferences
SharedPreferences pref = getApplicationContext().getSharedPreferences("myGlobalPrefTable", MODE_PRIVATE);
SharedPreferences.Editor editor = pref.edit();
//open a boolean to tell if the service is activated for the first time it will say false
boolean serviceStateOn = pref.getBoolean("isServiceActivated", false);
if(serviceStateOn == false){
//if ther serviceStateOn is false then there is no service running and it's fine to run a timer task
Toast.makeText(getApplicationContext(), "a New Timer Started with Delay: "+timerDeley, Toast.LENGTH_LONG).show();
editor.putBoolean("isServiceActivated", true); // getting String
editor.commit();
timer = new Timer();
timer.scheduleAtFixedRate(timerTask, timerDeley, timerDeley);
} else {
//if ther serviceStateOn is true then there is a service runing so just don't do anything
Log.d ("myLog", "Service is on so do nothing");
}
}
});
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(getApplicationContext(), "service stoped",
Toast.LENGTH_LONG).show();
}
}
my manifest file >
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.greenroad.candidate.mywallpaperchanger" >
<uses-permission android:name="android.permission.SET_WALLPAPER"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".myService"
android:exported="false"
/>
</application>
</manifest>
my main acticity >
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.preference.PreferenceManager;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import java.io.IOException;
public class MainActivity extends ActionBarActivity implements View.OnClickListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
//declaring all the buttons
Button comixButtonSuperman, comixButtonFlash, comixButtonCaptainAmerica, comixButtonThor, comixButtonWonderWoman;
Button startServiceButton, stopServiceButton;
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//casting and connecting the buttons to the actual buttons
comixButtonSuperman = (Button) findViewById(R.id.BT_wallpaper1);
comixButtonFlash = (Button) findViewById(R.id.BT_wallpaper2);
comixButtonCaptainAmerica = (Button) findViewById(R.id.BT_wallpaper3);
comixButtonThor = (Button) findViewById(R.id.BT_wallpaper4);
comixButtonWonderWoman = (Button) findViewById(R.id.BT_wallpaper5);
startServiceButton = (Button) findViewById(R.id.BT_startService);
stopServiceButton = (Button) findViewById(R.id.BT_stopService);
//adding listeners for all the buttons
comixButtonSuperman.setOnClickListener(this);
comixButtonFlash.setOnClickListener(this);
comixButtonCaptainAmerica.setOnClickListener(this);
comixButtonThor.setOnClickListener(this);
comixButtonWonderWoman.setOnClickListener(this);
startServiceButton.setOnClickListener(this);
stopServiceButton.setOnClickListener(this);
}
#Override
protected void onDestroy() {
super.onDestroy();
Log.d ("myLog", "Application exists here");
// when going to suspend the service is destroyd, so we should change the boolean to indicate this
//also this will make the service statement added in the service possible.
SharedPreferences pref = getApplicationContext().getSharedPreferences("myGlobalPrefTable", MODE_PRIVATE);
SharedPreferences.Editor editor7 = pref.edit();
editor7.putBoolean("isServiceActivated", false); // getting String
editor7.commit();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
//maybe will add options in a later date
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.BT_wallpaper1: // superman button
//was used for testings
break;
case R.id.BT_wallpaper2: // flash button
//was used for testings
break;
case R.id.BT_wallpaper3: // captain america button
//was used for testings
break;
case R.id.BT_wallpaper4: // thor button
//was used for testings
break;
case R.id.BT_wallpaper5: // wonder woman button
//was used for testings
break;
case R.id.BT_startService: // starts the service
//starts the service up
Intent i= new Intent(this, myService.class);
startService(i);
break;
case R.id.BT_stopService: // stops the service
//stop the service
Intent j= new Intent(this, myService.class);
stopService(j);
//updates ths shared prefrence that there is no service suning any moew
SharedPreferences pref = getApplicationContext().getSharedPreferences("myGlobalPrefTable", MODE_PRIVATE);
SharedPreferences.Editor editor7 = pref.edit();
editor7.putBoolean("isServiceActivated", false); // getting String
editor7.commit();
break;
}
}
}

I believe for this case you should use the AlarmManager instead of timer + handler. It gives you a way to perform time-based operations outside the lifetime of your application.
Here is an example of scheduling using AlarmManager
https://stackoverflow.com/a/8801990/1163224
I decided to add as nipped of code how to use AlarmManager to make my answer more complete
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.PowerManager;
import android.widget.Toast;
public class Alarm extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "");
wl.acquire();
// Put here YOUR code.
Toast.makeText(context, "Alarm !!!!!!!!!!", Toast.LENGTH_LONG).show(); // For example
wl.release();
}
public void SetAlarm(Context context)
{
AlarmManager am =( AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, Alarm.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000 * 60 * 10, pi); // Millisec * Second * Minute
}
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);
}
}
Add to Manifest.xml:
<uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission>
<receiver android:process=":remote" android:name=".Alarm"></receiver>
Service
public class YourService extends Service
{
Alarm alarm = new Alarm();
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
alarm.SetAlarm(this);
return START_STICKY;
}
....
}
In the Link above is a full code of how to create a service and start a service on boot
Hope you find my answer useful. :)

Related

Android Alarm Clock NullException

I'm beginner for Android Studio.
Currently, I'm trying to make the alarm clock by using the Android Studio. I have some error when trying to run the code. When it starts to run, it gives me these lines of error.
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.google.alarmclock, PID: 2837
java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.google.alarmclock/com.google.alarmclock.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2548)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference
at android.content.ComponentName.<init>(ComponentName.java:128)
at android.content.Intent.<init>(Intent.java:4868)
at com.google.alarmclock.MainActivity.<init>(MainActivity.java:30)
at java.lang.Class.newInstance(Native Method)
at android.app.Instrumentation.newActivity(Instrumentation.java:1078)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2538)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707) 
at android.app.ActivityThread.-wrap12(ActivityThread.java) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460) 
at android.os.Handler.dispatchMessage(Handler.java:102) 
at android.os.Looper.loop(Looper.java:154) 
at android.app.ActivityThread.main(ActivityThread.java:6077) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755) 
and this is my java file.
Alarm_Receiver.java
package com.google.alarmclock;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class Alarm_Receiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.e("We are in the Receiver","yaa");
//fetch extra strings from the intent
String get_your_string = intent.getExtras().getString("extra");
Log.e("What is the key?", get_your_string);
//create an intent to the ringtone service
Intent service_intent=new Intent(context,RingtonePlayingService.class);
//pass the extra string from Main Activity to the Ringtone Playing Service
service_intent.putExtra("extra",get_your_string);
//start the ringtone service
context.startService(service_intent);
}
}
RingtonePlayingService.java
package com.google.alarmclock;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;
import android.widget.Toast;
import java.security.Provider;
import java.util.List;
import java.util.Map;
public class RingtonePlayingService extends Service {
MediaPlayer media_song;
int startId;
boolean isRunning;
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("LocalService", "Received start id " + startId + ": " + intent);
//fetch the extra string values
String state = intent.getExtras().getString("extra");
Log.e("Ringtone extra is",state);
//this converts the extra strings from the intent
//to start IDs, values 0 or 1
assert state !=null;
switch (state) {
case "alarm on":
startId = 1;
break;
case "alarm off":
startId = 0;
Log.e("Start ID is ",state);
break;
default:
startId = 0;
break;
}
//if else statements
//if there is no music playing, and the user pressed "alarm on"
//music should start playing
if (!this.isRunning && startId==1) {
Log.e("there is no music, ","and you want start");
//create an instance of the media player
media_song = MediaPlayer.create(this,R.raw.i_am_singer);
media_song.start();
this.isRunning=true;
this.startId=0;
//put the notification here,test it out
//notification
//set up the notification service
NotificationManager notify_manager=(NotificationManager)
getSystemService(NOTIFICATION_SERVICE);
//set up an intent that goes to the Main Activity
Intent intent_main_activity=new Intent(this.getApplicationContext(),MainActivity.class);
//set up a pending intent
PendingIntent pending_intent_main_activity=PendingIntent.getActivity(this,0,
intent_main_activity,0);
//make the notification parameters
Notification notification_popup=new Notification.Builder(this)
.setContentTitle("An alarm is going off!")
.setContentText("Click Me")
.setContentIntent(pending_intent_main_activity)
.setAutoCancel(true)
.build();
//set up the notification call command
notify_manager.notify(0,notification_popup);
}
//if there is music playing, and the user pressed "alarm off"
//music should stop playing
else if (this.isRunning && startId == 0) {
Log.e("there is music, ","and you want end");
//stop the ringtone
media_song.stop();
media_song.reset();
this.isRunning=false;
this.startId=0;
}
//there are if user presses random buttons
//just to bug-proof the app
//if there is no music playing, and the user pressed "alarm off"
//do nothing
else if (!this.isRunning && startId == 0) {
Log.e("there is no music, ","and you want end");
//stop the ringtone
this.isRunning=false;
this.startId=0;
}
//if there is music playing and the user pressed "alarm on"
//do nothing
else if (this.isRunning && startId ==1) {
Log.e("there is music, ","and you want start");
this.isRunning =true;
this.startId=1;
}
//can't think of anything else, just to catch the odd event
else {
Log.e("else ","somehow you reached ");
}
return START_NOT_STICKY;
}
#Override
public void onDestroy() {
// Tell the user we stopped.
Log.e("on Destroy called","ta da");
super.onDestroy();;
this.isRunning=false;
Toast.makeText(this, "on Destroy called ", Toast.LENGTH_SHORT).show();
}
}
MainActivity.java
package com.google.alarmclock;
import android.annotation.TargetApi;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Button;
import android.widget.TextView;
import android.widget.TimePicker;
import java.util.Calendar;
public class MainActivity extends AppCompatActivity {
//to make alarm manager
AlarmManager alarm_manager;
TimePicker alarm_timepicker;
TextView update_text;
Context context;
PendingIntent pendingIntent;
final Intent my_intent=new Intent(this.context,Alarm_Receiver.class);
//create an instance of a calender
final Calendar calendar= Calendar.getInstance();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
this.context = this;
//initialize alarm manager
alarm_manager=(AlarmManager)getSystemService(ALARM_SERVICE);
//initialize timepicker
alarm_timepicker=(TimePicker)findViewById(R.id.timePicker);
//initialize our text update box
update_text=(TextView)findViewById(R.id.update_text);
//initialize start buttons
// Button start_alarm=(Button)findViewById(R.id.start_alarm);
//initialize the stop button
//Button stop_button=(Button)findViewById(R.id.end_alarm);
//Create an intent to the Alarm Receiver class
}
//create an onClick listener to start the alarm
#TargetApi(Build.VERSION_CODES.M)
public void onClickStartAlarm(View view)
{
//setting calendar instance with the hour and minute that have picked
//on the time picker
calendar.set(Calendar.HOUR_OF_DAY,alarm_timepicker.getHour());
calendar.set(Calendar.MINUTE,alarm_timepicker.getMinute());
//get the string values of the hour and minute
int hour=alarm_timepicker.getHour();
int minute=alarm_timepicker.getMinute();
//convert the int values to Strings
String hour_string=String.valueOf(hour);
String minute_string=String.valueOf(minute);
//convert 24 hour time to 12 hour time
if(hour>12)
{
hour_string="0" + String.valueOf(hour -12);
}
if(minute<10)
{
//10:7 --> 10:07
minute_string=String.valueOf(minute);
}
//method that changes the update text Textbox
set_alarm_text("Alarm On: " + hour_string + ":" +minute_string);
//put in extra string into my_intent
//tells the clock that you pressed the "alarm on" button
my_intent.putExtra("extra","on");
//Create a pending intent that delays the intent
//until the specified calendar time
pendingIntent = PendingIntent.getBroadcast(MainActivity.this,0,my_intent,PendingIntent.FLAG_UPDATE_CURRENT);
//set the alarm manager
alarm_manager.set(AlarmManager.RTC_WAKEUP,calendar.getTimeInMillis(),pendingIntent);
}
private void set_alarm_text(String output) {
update_text.setText(output);
}
//create an onClick listener to stop the alarm or undo an alarm set
public void onClickStopAlarm(View view)
{
//method that changes the update text Textbox
set_alarm_text("Alarm off!");
//Cancel the alarm
alarm_manager.cancel(pendingIntent);
//put extra string into my_intent
//tells the clock that you pressed the "alarm off" button
my_intent.putExtra("extra","off");
//Stop the ringtone
sendBroadcast(my_intent);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<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"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".Alarm_Receiver"/>
<service android:name=".RingtonePlayingService"
android:enabled="true"/>
</application>
build.gradle
apply plugin: 'com.android.application'
android {
compileSdkVersion 24
buildToolsVersion "24.0.2"
defaultConfig {
applicationId "com.google.alarmclock"
minSdkVersion 16
targetSdkVersion 24
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:24.2.1'
compile 'com.android.support:design:24.2.1'
testCompile 'junit:junit:4.12'
}
Please help me solve the problem. Thank you
You should declare Calender object out side onCreate and initialise it inside onCreate.
Calendar calendar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
calendar= Calendar.getInstance();
...
}
Plus you'll still get NullPointerException, because At this line
final Intent my_intent=new Intent(this.context,Alarm_Receiver.class);
your context will be null. so you can do same for that.
Intent my_intent;
Calendar calendar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
this.context = this;
calendar= Calendar.getInstance();
my_intent=new Intent(this.context,Alarm_Receiver.class);
...
}
Happy coding.
Chnage this line final Calendar calendar = Calendar.getInstance(); as below.
Initialize it in onCreate()
...
//create an instance of a calender
//final Calendar calendar= Calendar.getInstance();
Calendar calendar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
calendar= Calendar.getInstance();
...
}

Alarm app is not setting any alarm - Android

I am working on an app which will set the alarm automatically. I have googled a lot and found some solution and made some changes and prepare a code but this code is not working. It is always toasting a message Alarm is null .
Do not know why, can any one please help me out of this? Thanks in advance:
Here is the code :
AlarmManagerBroadcastReceiver Class
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.PowerManager;
import android.widget.Toast;
public class AlarmManagerBroadcastReceiver extends BroadcastReceiver {
final public static String ONE_TIME = "oneTime";
private Context contx;
public void AlarmManagerBroadcastReceiver()
{
}
#Override
public void onReceive(Context context, Intent intent) {
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "YOUR TAG");
//Acquire the lock
wl.acquire();
//You can do the processing here.
Bundle extras = intent.getExtras();
StringBuilder msgStr = new StringBuilder();
if(extras != null && extras.getBoolean(ONE_TIME, Boolean.FALSE)){
//Make sure this intent has been sent by the one-time timer button.
msgStr.append("One time Timer : ");
}
Format formatter = new SimpleDateFormat("hh:mm:ss a");
msgStr.append(formatter.format(new Date()));
Toast.makeText(context, msgStr, Toast.LENGTH_LONG).show();
//Release the lock
wl.release();
}
public void SetAlarm(Context context)
{
AlarmManager am=(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmManagerBroadcastReceiver.class);
intent.putExtra(ONE_TIME, Boolean.FALSE);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, 0);
//After after 5 seconds
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000 * 5 , pi);
}
}
Main Activity:
import com.test.alarmtest.AlarmManagerBroadcastReceiver;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends Activity {
private AlarmManagerBroadcastReceiver alarm;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/*
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(new CameraPreview(this));
*/
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
public void alarm(View view) {
AlarmManagerBroadcastReceiver alarmclock = new AlarmManagerBroadcastReceiver();
if(alarm != null){
alarm.SetAlarm(getBaseContext());
}else{
Toast.makeText(getBaseContext(), "Alarm is null", Toast.LENGTH_SHORT).show();
}
}
}
Main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.test.cameraapp.MainActivity" >
<Button
android:id="#+id/button2"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="#+id/button1"
android:layout_alignBottom="#+id/button1"
android:layout_marginRight="23dp"
android:layout_toLeftOf="#+id/button1"
android:text="setAlarm"
android:onClick="alarm" />
</RelativeLayout>
You are checking for alarm but should be checking for alarmclock as that is what you created in this line:
AlarmManagerBroadcastReceiver alarmclock = new AlarmManagerBroadcastReceiver();
Change your if statement to the following
if(alarmclock != null) {
alarmclock.SetAlarm(getBaseContext());
}
else {
Toast.makeText(getBaseContext(), "Alarm is null", Toast.LENGTH_SHORT).show();
}

Keep a service running even if app is closed

I am implementing Service for receiving push notifications in Android device. The notifications are successfully received when app is in foreground. When app is closed and its instance is cleared from task manager, notifications are not received.
I want to keep the service running at all the times and it should not stop even if the app is cleared from the task manager.
I start the service from my activity in a button click. When i click the button my service starts and it gives me Toast notification every one minute but if I press the back button then also my service is running but , as soon as i clear my app from the recent activity list which is shown on long press of home button my service is stoped and if again i start my app and check the status of the service but its not running.
I want my service to run even if my app is closed.
This is my activity class
package com.example.hello;
import java.util.ArrayList;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ListView;
public class MainActivity extends Activity {
Button btnSer;
int Pointer=0;
ListView lv;
ArrayList<String> alist=new ArrayList<String>();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnSer=(Button) findViewById(R.id.btnstart);
btnSer.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
//start the service when the button is clicked
Log.e("","status of service : "+isMyServiceRunning(MyService.class));
//if(!isMyServiceRunning(MyService.class))
startService(new Intent(getApplicationContext(), MyService.class));
}
});
}
//check if the service is running
private boolean isMyServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
This is my Service class.
package com.example.hello;
import java.util.Calendar;
import android.app.Service;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
public class MyService extends Service{
private Handler handlerList = new Handler();
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
//TODO do something useful
Toast.makeText(getApplicationContext(), "On start command called", Toast.LENGTH_LONG).show();
return Service.START_STICKY;
}
public void updateLists(){
handlerList.postDelayed(mUpdateListTask, 1000*60);
}
private Runnable mUpdateListTask = new Runnable() {
public void run() { //will make a toast notification every 1 minute.
Calendar cal = Calendar.getInstance();
Log.e("","Thread executed at "+cal.get(Calendar.HOUR_OF_DAY)+":"+cal.get(Calendar.MINUTE)+":"+cal.get(Calendar.SECOND)+":");
Toast.makeText(getApplicationContext(), "Thread executed at "+cal.get(Calendar.HOUR_OF_DAY)+":"+cal.get(Calendar.MINUTE)+":"+cal.get(Calendar.SECOND)+":", Toast.LENGTH_LONG).show();
handlerList.postDelayed(this, 1000*60);
}};
#Override
public void onCreate() {
updateLists();
Toast.makeText(this, "Congrats! MyService Created", Toast.LENGTH_LONG).show();
Log.d("", "onCreate in service");
}
#Override
public void onStart(Intent intent, int startId) {
Toast.makeText(this, "My Service Started", Toast.LENGTH_LONG).show();
Log.d("", "onStart in service");
}
#Override
public void onDestroy() {
Toast.makeText(this, "MyService Stopped", Toast.LENGTH_LONG).show();
Log.d("", "onDestroy in service");
}
}
also added the permission in manifest file
<uses-permission android:name="android.permission.WAKE_LOCK" />
Start it as foreground service in the activity use startforeground(intent name) and return it as sticky in the service onstartCommand() method.

background services stop when the app is closed via the BACK button

A background service in Android stops running when the user exits the app using the BACK button. The same service works fine if the app is in foreground or in background (clicking the HOME button).
there are 3 cases:
Keep the app running: every 15 seconds a notification is shown (OK).
Put the app in background by clicking the HOME button: notifications keep showing (OK)
Click the BACK button (this closes the app): the background service is stopped and no more notifications are shown (BUG)
Expected behavior
Also in case #3, the notifications should keep running every 15 seconds.
my entire source is below
MainActivity.java
package com.example.service_demo;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity implements OnClickListener {
private TextView timerValue;
private Button startTimer;
private Button cancleTimer;
Intent i;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mapview();
}
private void mapview() {
timerValue = (TextView) findViewById(R.id.timertext);
startTimer = (Button) findViewById(R.id.starttimer);
cancleTimer = (Button) findViewById(R.id.cancletimer);
startTimer.setOnClickListener(this);
cancleTimer.setOnClickListener(this);
}
#Override
protected void onResume() {
super.onResume();
i = new Intent(this, SimpleService.class);
if (isMyServiceRunning()) {
Toast.makeText(getBaseContext(), "Service is running,",
Toast.LENGTH_SHORT).show();
registerReceiver(broadcastReceiver, new IntentFilter(
SimpleService.BROADCAST_ACTION));
startTimer.setEnabled(false);
} else {
Toast.makeText(getBaseContext(), "There is no service running",
Toast.LENGTH_SHORT).show();
}
}
#Override
public void onClick(View v) {
if (v == startTimer) {
startTimer.setEnabled(false);
i = new Intent(this, SimpleService.class);
startService(i);
registerReceiver(broadcastReceiver, new IntentFilter(
SimpleService.BROADCAST_ACTION));
} else if (v == cancleTimer) {
i = new Intent(this, SimpleService.class);
stopService(i);
timerValue.setText("00:00:00");
startTimer.setEnabled(true);
}
}
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
updateUI(intent);
}
};
private void updateUI(Intent intent) {
String str = intent.getStringExtra("textval");
timerValue.setText(str);
}
private boolean isMyServiceRunning() {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager
.getRunningServices(Integer.MAX_VALUE)) {
if (SimpleService.class.getName().equals(
service.service.getClassName())) {
return true;
}
}
return false;
}
#Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
i = new Intent(this, SimpleService.class);
startService(i);
}
#Override
public void onBackPressed() {
// TODO Auto-generated method stub
super.onBackPressed();
System.exit(0); // system.exit(0) is mendatory for my app so it can't be
// removed
}
}
SimpleService
package com.example.service_demo;
import java.util.Timer;
import java.util.TimerTask;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
public class SimpleService extends Service {
private NotificationManager mNM;
private long startTime = 0L;
long timeInMilliseconds = 0L;
long timeSwapBuff = 0L;
long updatedTime = 0L;
long basestart = System.currentTimeMillis();
Timer timer = new Timer();
long timeswap = 0L;
int secs = 0;
int mins = 0;
int hour = 0;
Intent intent;
String s;
public static final String BROADCAST_ACTION = "com.example.service_demo.MainActivity";
private int NOTIFICATION = 1;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
mNM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
intent = new Intent(BROADCAST_ACTION);
Toast.makeText(this, "Service Started", 2000).show();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Thread t = new Thread(new Runnable() {
#Override
public void run() {
timer.schedule(new RemindTask(), 0, 1000);
}
});
t.start();
return Service.START_NOT_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
mNM.cancel(NOTIFICATION);
if (timer != null) {
timer.cancel();
timer.purge();
timer = null;
}
Toast.makeText(this, "Service Stoped", 2000).show();
}
class RemindTask extends TimerTask {
#Override
public void run() {
timeInMilliseconds = System.currentTimeMillis() - basestart;
timeSwapBuff = timeswap;
updatedTime = timeSwapBuff + timeInMilliseconds;
secs = (int) (updatedTime / 1000);
mins = secs / 60;
hour = mins / 60;
secs = secs % 60;
mins = mins % 60;
s = "" + String.format("%02d", hour) + ":" + ""
+ String.format("%02d", mins) + ":"
+ String.format("%02d", secs);
if (s.equalsIgnoreCase("00:00:15")) {
showNotification();
}
intent.putExtra("textval", s);
sendBroadcast(intent);
}
}
private void showNotification() {
// In this sample, we'll use the same text for the ticker and the
// expanded notification
CharSequence text = s;
// Set the icon, scrolling text and timestamp
#SuppressWarnings("deprecation")
Notification notification = new Notification(R.drawable.ic_launcher,
text, System.currentTimeMillis());
// The PendingIntent to launch our activity if the user selects this
// notification
PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
new Intent(this, MainActivity.class), 0);
// Set the info for the views that show in the notification panel.
notification.setLatestEventInfo(this, "Notification Label", text,
contentIntent);
// Send the notification.
mNM.notify(NOTIFICATION, notification);
}
}
In the method onStartCommand() of the service, return START_STICKY.
The service will continue to run until you explicitly call stopSelf() in the service or call stopService() from your activity.
Try implementing foreground service. foreground service
Foreground service displays notification and is never stopped.
Implement this code snippet in your service's onCreate().
Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text),
System.currentTimeMillis());
Intent notificationIntent = new Intent(this, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, getText(R.string.notification_title),
getText(R.string.notification_message), pendingIntent);
startForeground(ONGOING_NOTIFICATION_ID, notification);
This works for me:
notifyIntent.setAction(Intent.ACTION_MAIN);
notifyIntent.addCategory(Intent.CATEGORY_LAUNCHER);

Android Dialer in the Background

Is it possible to call the Intent.ACTION_CALL in the background ?
I want my application to call but I don't want it to put in the background, I want it to stay in the foreground while it is calling.
The Intent.ACTION_CALL will call the default Android Phone activity and call the number you provided. If you want your App to be in the foreground, which i take to understanding you are builder your own calling app, you will have to implement the Calling part yourself.
Otherwise you can launch your activity with say a 5 seconds delay if you just want to show the user a context of your application.
You can invoke your activity after making a call using this,
package com.sdi.androidcall;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity {
Button call;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
call = (Button) findViewById(R.id.call);
final PhoneCallListener phoneListener = new PhoneCallListener();
final TelephonyManager telephonyManager = (TelephonyManager) this
.getSystemService(Context.TELEPHONY_SERVICE);
call.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
try {
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setData(Uri.parse("tel:" + phoneNumber));
startActivity(callIntent);
} catch (ActivityNotFoundException e) {
e.printStackTrace();
}
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
telephonyManager.listen(phoneListener,
PhoneStateListener.LISTEN_CALL_STATE);
}
}, 10000);
}
});
}
private class PhoneCallListener extends PhoneStateListener {
boolean flag = true;
String LOG_TAG = "Call TEST";
#Override
public void onCallStateChanged(int state, String incomingNumber) {
if (TelephonyManager.CALL_STATE_RINGING == state) {
Log.i(LOG_TAG, "number: " + incomingNumber);
}
if (TelephonyManager.CALL_STATE_OFFHOOK == state) {
Log.i(LOG_TAG, "OFFHOOK");
// invoking activity
if (flag) {
Intent i = getBaseContext().getPackageManager()
.getLaunchIntentForPackage(
getBaseContext().getPackageName());
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
System.out.println("flagged retrieving app");
flag = false;
}
}
if (TelephonyManager.CALL_STATE_IDLE == state) {
Log.i(LOG_TAG, "IDLE");
Log.i(LOG_TAG, "restart app");
}
}
}
}
The activity will be called after a delay of 10 seconds here using PhoneStateListener
You need to specify the intent permissions in the mainfest as
<uses-permission android:name="android.permission.CALL_PHONE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
Try it, let me know if worked.

Categories

Resources