gpt4 book ai didi

java - 线程在后台使用 JobService 时停止运行

转载 作者:行者123 更新时间:2023-11-30 04:53:58 26 4
gpt4 key购买 nike

我正在创建一个 sleep 定时器应用程序,它会随着时间的流逝逐渐降低系统音量。如果用户将时间设置为 30 分钟,则音量将在 15 分钟和 7.5 分钟等处减小。

我目前将音量衰减发送到 JobService,它在我的手机屏幕上显示时工作正常,但一旦我锁定手机并将其留在后台,它将工作一段时间几分钟的顶部。我也尝试过使用 ServiceIntentService,两者都产生了相似的结果。

我想知道这些线程是否认为它们已完成,即使它们没有完成,因为我正在使用一个调用自身的 handle.postDelayed

为什么它不会在后台运行超过几分钟?我是否需要在 onStartJob 内部设置一个检查器来查看 startVolumeDecrement 是否已完成?

以下是相关代码(完整代码在文章底部):

主 Activity .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
}

}

我的 list 文件

<?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

最佳答案

因为当你锁定你的手机操作系统时,如果许多服务在不同的应用程序中运行并且我在构建测验应用程序时遇到同样的问题,那么你的手机操作系统将暂停正在运行的服务。所以解决方案是你可以使用 WAKE LOCK 它解决了这个问题。

Activity 中:

    private var wakeLock: PowerManager.WakeLock? = null

启动唤醒锁:

    var powerManager = getSystemService(POWER_SERVICE) as PowerManager
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"ExampleApp:Wakelock Started")
wakeLock?.acquire()

释放唤醒锁最重要的一步:

  if (wakeLock?.isHeld!!) {
L.e("ExampleApp", "Wakelock Released")
wakeLock?.release();
}

最后在 list 中添加权限:

  <uses-permission android:name="android.permission.WAKE_LOCK" />

关于java - 线程在后台使用 JobService 时停止运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59540742/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com