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

问题描述 投票:1回答:1

我正在创建一个睡眠计时器应用程序,该应用程序会随着时间的流逝逐渐降低系统的音量。如果用户将时间设置为30分钟,则音量将减小为15分钟,然后是7.5分钟,依此类推。

我目前有将音量衰减发送到JobService

的功能,当它在手机屏幕上显示时,效果很好,但是一旦我锁定手机并将其放在后台,它就会在顶部工作几分钟。我也尝试使用ServiceIntentService,它们都产生相似的结果。

我想知道这些线程是否认为它们已经完成,即使它们尚未完成,因为我使用的是一个调用自身的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 ...

java android java-threads background-thread
1个回答
0
投票
因为当您锁定手机时,如果许多服务在不同的应用程序中运行,并且在构建测验应用程序时遇到相同的问题,操作系统将暂停正在运行的服务。因此,解决方案是可以使用唤醒锁定来解决问题。
© www.soinside.com 2019 - 2024. All rights reserved.