Я создаю приложение, в котором есть кнопка изображения, которая запускает Сервис при нажатии. Служба содержит обработчик, который я использую в качестве 24-часового таймера. Когда Служба запущена, кнопка отключена, поэтому ее нельзя нажать снова. Затем, когда время увеличивается, кнопка снова включается. Все это отлично работает, пока приложение не будет полностью закрыто. Если приложение полностью закрыто, Служба продолжает работать так, как должна, но существует проблема с BroadcastReceiver. Если приложение закрыто, а затем снова открыто, кнопка запуска службы может быть нажата, даже если служба уже запущена. Я не уверен, почему кнопка включена, когда приложение снова открывается, хотя служба все еще работает.BroadcastReceiver from Service не работает правильно, когда приложение закрыто
Вот код для моей службы:
public class SetupTimerPC1 extends Service
{
Handler handler;
Database data;
Intent i, result;
runGraphics runG;
int bucketLevel = 1, bucketExpTotal = 0, totalWater = 0, bucketExp = 0;
float waterAmt = 0;
int timerCount = 0;
Notification notify;
Notification.Builder builder;
NotificationManager notificationManager;
PendingIntent pendingIntent;
@Override
public IBinder onBind(Intent intent)
{
return null;
}//end onBind function
@Override
public void onRebind(Intent intent)
{
super.onRebind(intent);
}//end onRebing
@Override
public boolean onUnbind(Intent intent)
{
return true;
}//end onUnbind
@Override
public void onCreate()
{
super.onCreate();
//setup 24 hour timer
handler = new Handler(Looper.getMainLooper());
handler.postDelayed(runnable, 2000); //600000 -> wait ten minutes then call runnable
}//end onCreate function
private Runnable runnable = new Runnable()
{
public void run()
{
//get current bucket exp
data = new Database(SetupTimerPC1.this);
data.open();
bucketExp = data.getBucketExp();
data.close();
//check experience for current level
if (bucketExp < 3000)
{
bucketLevel = 1;
}//end if
else if (bucketExp > 3000 && bucketExp < 6000)
{
bucketLevel = 2;
}//end else if
else if (bucketExp > 6000 && bucketExp < 9000)
{
bucketLevel = 3;
}//end else if
else if (bucketExp > 9000 && bucketExp < 12000)
{
bucketLevel = 4;
}//end else if
else if (bucketExp > 12000)
{
bucketLevel = 5;
}//end else if
//give resource based on level
if (bucketLevel == 1)
{
waterAmt += .2;
bucketExp += 1;
}//end if
else if (bucketLevel == 2)
{
waterAmt += .4;
bucketExp += 2;
}//end else if
else if (bucketLevel == 3)
{
waterAmt += .6;
bucketExp += 3;
}//end else if
else if (bucketLevel == 4)
{
waterAmt += .8;
bucketExp += 4;
}//end else if
else if (bucketLevel == 5)
{
waterAmt += 1.0;
bucketExp += 5;
}//end else if
timerCount++;
if (timerCount < 5)//144
{
handler.postDelayed(runnable, 2000); //600000
}//end if
else
{
//pull data
data = new Database(SetupTimerPC1.this);
data.open();
bucketExpTotal = data.getBucketExp();
totalWater = data.getWaterAmt();
data.close();
//add new data to old
bucketExpTotal += bucketExp;
totalWater += (int)waterAmt;
//push data
data.open();
data.bucketExpEntry(bucketExpTotal);
data.waterAmountEntry(totalWater);
data.bucketLevelEntry(bucketLevel);
data.close();
//send notification that resources have been gained
notifyUser();
i.putExtra("polarCap1Stat", true);
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(i);
handler.removeCallbacks(runnable);
}//end else
}//end run function
};//end runnable
public void notifyUser()
{
//notify user of resource gain
result = new Intent(this, runGraphics.class);
pendingIntent = PendingIntent.getActivity(
SetupTimerPC1.this,
0,
result,
Intent.FLAG_ACTIVITY_NEW_TASK);
notify = new Notification.Builder(getApplicationContext())
.setContentTitle("2023: Water Gained")
.setContentText("Successfully extracted water.")
.setTicker("2023")
.setWhen(System.currentTimeMillis())
.setContentIntent(pendingIntent)
.setDefaults(Notification.DEFAULT_SOUND)
.setAutoCancel(true)
.setSmallIcon(R.drawable.alienicon)
.build();
notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, notify);
}//end notifyUser
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
i = new Intent("polarCap1Status");
i.putExtra("polarCap1Stat", false);
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(i);
return Service.START_STICKY;
}//end onStartCommand function
} // конец SetupTimerPC1 класс
Вот код для кнопки, которая принимает логическое значение из BroadcastReceiver:
//setup image buttons
polarCap1 = (ImageButton) findViewById(R.id.polarCapButton1);
polarCap1.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
Toast.makeText(getApplicationContext(), "Attempting to Gain Resources", Toast.LENGTH_SHORT).show();
if (polarCap1.isEnabled() && appSound)
{
water = new SoundPool(2, AudioManager.STREAM_MUSIC, 0);
playSound = water.load(runGraphics.this, R.raw.watersound, 1);
//play water sound
water.setOnLoadCompleteListener(new OnLoadCompleteListener()
{
@Override
public void onLoadComplete(SoundPool soundPool,
int sampleId, int status)
{
water.play(playSound, 1, 1, 0, 0, 1);
}//end onLoadComplete
});//end setOnLoadCompleteListener
}//end if
//button cannot be clicked
polarCap1.setEnabled(false);
//start service for timer
startService(new Intent(runGraphics.this, SetupTimerPC1.class));
//stop service for timer
//stopService(new Intent(runGraphics.this, SetupTimerPC1.class));
//broadcast receiver to allow button to be clicked again
mMessageReceiver1 = new BroadcastReceiver()
{
@Override
public void onReceive(Context context, Intent intent)
{
clickOnOff1 = intent.getBooleanExtra("polarCap1Stat", false);
polarCap1.setEnabled(clickOnOff1);
updateScores();
}//end onReceive function
};
LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(mMessageReceiver1, new IntentFilter("polarCap1Status"));
}//end onClick function
});//end setOnClickListener
Большое вам спасибо за помощь.
Могу ли я это сделать и все еще работать, когда приложение полностью закрыто? И возможно ли, чтобы я сохранил это, как у меня? – sboehnke
AlarmManager будет запускать будильник каждые 24 часа (или на любой другой интервал), даже если ваше приложение полностью уничтожено системой. В отличие от Службы, которая может быть убита и больше не будет стрелять. Поэтому, если вы держите его на своем пути, вы не можете быть уверены, что будильник погаснет. С AlarmManager вы всегда уверены. –