我正在创建一个睡眠计时器应用程序,该应用程序会随着时间的流逝逐渐降低系统的音量。如果用户将时间设置为30分钟,则音量将减小为15分钟,然后是7.5分钟,依此类推。
我目前有将音量衰减发送到JobService
的功能,当它在手机屏幕上显示时,效果很好,但是一旦我锁定手机并将其放在后台,它就会在顶部工作几分钟。我也尝试使用Service和IntentService,它们都产生相似的结果。我想知道这些线程是否认为它们已经完成,即使它们尚未完成,因为我使用的是一个调用自身的handle.postDelayed
。为什么它不能在后台运行超过几分钟?我是否需要在[[onStartJob
内部使用检查器,以查看startVolumeDecrement是否完成? 下面是相关代码(完整的代码在文章的最底部):MainActivity.java
package com.example.dreamquiet;
//imports
/.../
public class MainActivity extends AppCompatActivity {
//Methods:
@Override
protected void onCreate(Bundle savedInstanceState) { //method that does it all!
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startDecay()
}
public void startDecay(){
//this is used to pass the time to the job.
PersistableBundle bundle = new PersistableBundle();
bundle.putInt("totsleep", totalSleepTime);
JobScheduler jobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
JobInfo jobInfo = new JobInfo.Builder(11, new ComponentName(this, StartDecayJob.class))
// only add if network access is required
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
.setExtras(bundle) //this is used to pass the time to the job.
.build();
jobScheduler.schedule(jobInfo);
}
public void stopDecay(){
JobScheduler jobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
jobScheduler.cancelAll();
}
StartDecayJob.java
package com.example.dreamquiet;
//bunch of imports
/..../
public class StartDecayJob extends JobService {
protected int counter;
protected int totalSleepTime;
protected boolean isDone;
final Handler handleDecay = new Handler();
@Override
public boolean onStartJob(JobParameters jobParameters) {
totalSleepTime = jobParameters.getExtras().getInt("totsleep");
startVolumeDecrement();
return true;
}
@Override
public boolean onStopJob(JobParameters jobParameters) {
handleDecay.removeCallbacksAndMessages(null); //wipe out the current startVolumeDecrement
super.onDestroy();
stopSelf();
Toast.makeText(this, "Goodnight :)", Toast.LENGTH_LONG).show();
// return true to restart the job
return false;
}
//the method that lowers the volume over time.
protected void startVolumeDecrement() {
//get the audio
final AudioManager phoneVolume = (AudioManager) getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
int currentVolume = phoneVolume.getStreamVolume(AudioManager.STREAM_MUSIC);
//get the vector. Yes it's ugly. enjoy it.
Vector decayVector = new Vector();
decayVector = populateDecay(totalSleepTime, decayVector, currentVolume);
final Vector decay = decayVector;
counter = 0; //Reset the counter --> safe :P
final Runnable volDecay = new Runnable(){
public void run(){
if(counter >= decay.size()-1 || phoneVolume.getStreamVolume(AudioManager.STREAM_MUSIC) == 0){
//if current volume isn't muted then MUTE IT!
if(phoneVolume.getStreamVolume(AudioManager.STREAM_MUSIC) > 0){
counter--;
handleDecay.postDelayed(this, ((int)decay.get(decay.size()-1)));
}
//If using spotify, it will pause it! :)
Intent pauseSpotify = new Intent("com.spotify.mobile.android.ui.widget.PLAY");
pauseSpotify.setPackage("com.spotify.music");
sendBroadcast(pauseSpotify);
return; //return is redundant but why not...
}
//decrease volume then recall function
phoneVolume.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_LOWER, AudioManager.FLAG_SHOW_UI);
handleDecay.postDelayed(this, ((int) decay.get(counter++)));
}
};
handleDecay.postDelayed(volDecay, ((int) decay.get(counter++))); //start the initial counter
}
}
我的清单文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.dreamquiet" >
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"></uses-permission> <!--preventitive measures-->
<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" >
<activity android:name=".MainActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data
android:name="preloaded_fonts"
android:resource="@array/preloaded_fonts" />
<!-- intent defined in this service tag below -->
<service android:name=".StartDecayJob"
android:label="decay"
android:permission="android.permission.BIND_JOB_SERVICE"/> <!--Gotta see if process will work -->
</application>
</manifest>
Full code here
我正在创建一个睡眠计时器应用程序,该应用程序会随着时间的流逝逐渐降低系统的音量。如果用户将时间设置为30分钟,则音量将减少15分钟,然后是7.5分钟,依此类推。I ...