Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/318.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在环境模式下更频繁地更新不工作-Android Wear/WearOS_Java_Android_Wear Os_Android Wear 2.0_Ambient - Fatal编程技术网

Java 在环境模式下更频繁地更新不工作-Android Wear/WearOS

Java 在环境模式下更频繁地更新不工作-Android Wear/WearOS,java,android,wear-os,android-wear-2.0,ambient,Java,Android,Wear Os,Android Wear 2.0,Ambient,我目前正在开发一个支持ambient mjode的应用程序。这并不难。现在,我的应用程序有两个计时器,需要每秒更新一次。 所以我选择了谷歌文档。我已经尝试了很多次,我检查了文档中建议的每一行代码,但是我无法让它正常工作 当模拟器或手表进入环境模式时,计时器将持续几秒钟,然后停止几秒钟。然后更新1-3次,然后再次停止。奇怪的是,这种情况没有任何形式 我一点也不知道如何处理这个问题 编辑:在emulator中运行时,它看起来或多或少是5秒的间隔。但是,当我将triggerTimeMs-Current

我目前正在开发一个支持ambient mjode的应用程序。这并不难。现在,我的应用程序有两个计时器,需要每秒更新一次。 所以我选择了谷歌文档。我已经尝试了很多次,我检查了文档中建议的每一行代码,但是我无法让它正常工作

当模拟器或手表进入环境模式时,计时器将持续几秒钟,然后停止几秒钟。然后更新1-3次,然后再次停止。奇怪的是,这种情况没有任何形式

我一点也不知道如何处理这个问题

编辑:在emulator中运行时,它看起来或多或少是5秒的间隔。但是,当我将triggerTimeMs-CurrenttimeMs输出到日志时,它总是显示1,这从技术上来说意味着报警已安排在下一秒

这是我的密码:

import android.app.AlarmManager;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.*;
import android.support.constraint.ConstraintLayout;
import android.support.v4.app.FragmentActivity;
import android.support.v4.content.ContextCompat;
import android.support.wear.ambient.AmbientModeSupport;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Chronometer;
import android.widget.TextClock;
import android.widget.TextView;
import android.widget.Toast;
import android.support.v4.app.NotificationCompat;

import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.TimeUnit;

public class TimerActivity extends FragmentActivity implements AmbientModeSupport.AmbientCallbackProvider {

    @Override
    public AmbientModeSupport.AmbientCallback getAmbientCallback() {
        return new MyAmbientCallback();
    }

    private static final String AMBIENT_UPDATE_ACTION = "de.jannisgoeing.sportstimerforwearos.action.AMBIENT_UPDATE";

    private static final int BURN_IN_OFFSET_PX = 10;
    boolean mIsLowBitAmbient;
    boolean mDoBurnInProtection;

    private AlarmManager mAmbientUpdateAlarmManager;
    private PendingIntent mAmbientUpdatePendingIntent;
    private BroadcastReceiver mAmbientUpdateBroadcastReceiver;

    private AmbientModeSupport.AmbientController mAmbientController;

    private ConstraintLayout timer_layout;
    private TextClock clock;
    private TextView timerName;
    private TextView sectionName;
    private long pauseOffset;
    private Intent intent;
    private Timer timer;
    private Button timerButton;
    private int timerStatus = 0;
    private TimerSection currentTimerSection;
    private int prev_timer_status;
    private TextView label_current;
    private TextView label_actual;

    private Chronometer current;
    private Chronometer actual;
    private Boolean running;

    private NotificationManager notificationManager;

    @SuppressWarnings( "deprecation" )
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_timer);

        // Enables Always-on
        mAmbientController = AmbientModeSupport.attach(this);

        mAmbientUpdateAlarmManager =
                (AlarmManager) getSystemService(Context.ALARM_SERVICE);

        Intent ambientUpdateIntent = new Intent(AMBIENT_UPDATE_ACTION);

        mAmbientUpdatePendingIntent = PendingIntent.getBroadcast(
                this, 0, ambientUpdateIntent, PendingIntent.FLAG_UPDATE_CURRENT);

        mAmbientUpdateBroadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                refreshDisplayAndSetNextUpdate();
            }
        };

        final Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
        notificationManager = getSystemService(NotificationManager.class);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            notificationManager.createNotificationChannel(
                    new NotificationChannel("timer", "Timer", NotificationManager.IMPORTANCE_HIGH)
            );
        }

        intent = this.getIntent();
        if (intent.getExtras() == null) {
            Toast.makeText(this, R.string.error_noProfilePassed, Toast.LENGTH_LONG).show();
            intent = new Intent(this, MainActivity.class);
            this.startActivity(intent);
        } else {
            timer = (Timer) intent.getSerializableExtra("TIMER");
        }

        if (timer == null) {
            Toast.makeText(this, R.string.error_noValidTimerPassed, Toast.LENGTH_LONG).show();
            intent = new Intent(this, MainActivity.class);
            this.startActivity(intent);
        }

        timer_layout = findViewById(R.id.timer_layout);

        clock = findViewById(R.id.textClock);
        clock.setFormat24Hour(clock.getFormat24Hour());

        timerName = findViewById(R.id.timerName);
        timerName.setText(timer.getName());

        current = findViewById(R.id.chronometerCurrent);
        actual = findViewById(R.id.chronometerActual);

        label_current = findViewById(R.id.labelCurrentTime);
        label_actual = findViewById(R.id.labelActualTime);

        currentTimerSection = getFirstTimerSection(timer);

        sectionName = findViewById(R.id.sectionName);
        sectionName.setText(currentTimerSection.getName());

        running = false;

        Intent stopIntent = new Intent("de.jannisgoeing.sportstimerforwearos.STOP");
        PendingIntent stopPendingIntent = PendingIntent.getBroadcast(this, 0, stopIntent, 0);
        Intent startIntent = new Intent("de.jannisgoeing.sportstimerforwearos.STARTPAUSE");
        PendingIntent startPendingIntent = PendingIntent.getBroadcast(this, 0, startIntent, 0);

        final NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
                .setWhen(System.currentTimeMillis() - SystemClock.elapsedRealtime() + current.getBase())
                .setUsesChronometer(false)
                .setContentText("Waiting for Next Section to start.")
                .setSmallIcon(timer.getIcon())
                .setAutoCancel(false)
                .setOngoing(true)
                .setOnlyAlertOnce(true)
                .setContentIntent(
                        PendingIntent.getActivity(this, 10,
                                new Intent(this, TimerActivity.class)
                        .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP),
                                0)
                )
                .addAction(running ? R.drawable.ic_pause_white
                        : R.drawable.ic_play_white,
                        running ? this.getString(R.string.button_pause)
                        : this.getString(R.string.button_resume),
                        startPendingIntent)
                .addAction(R.drawable.ic_stop_white, this.getString(R.string.button_end), stopPendingIntent);
        notificationManager.notify(1, builder.build());

        timerButton = findViewById(R.id.timerButton);
        timerButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                if(timerStatus == 0) { //0=Status: Not started
                    timerStatus = 1;
                    timerButton.setText(R.string.button_pause);
                    checkHeadStart();
                    builder.setWhen(System.currentTimeMillis() - SystemClock.elapsedRealtime() + current.getBase()).setUsesChronometer(true).setContentText("").build();
                    notificationManager.notify(1, builder.build());
                    current.start();
                    actual.start();
                    running = true;
                } else if (timerStatus == 1) { //1=Status: Running
                    timerStatus = 2;
                    timerButton.setText(R.string.button_resume);
                    pauseOffset = SystemClock.elapsedRealtime() - current.getBase();
                    builder.setUsesChronometer(false).setContentText("Paused").build();
                    notificationManager.notify(1, builder.build());
                    current.stop();
                    running = false;
                    if(currentTimerSection.getType() == 2) {
                        actual.stop();
                    }
                } else if (timerStatus == 2) { //2=Status: Paused
                    timerStatus = 1;
                    timerButton.setText(R.string.button_pause);

                    current.setBase(SystemClock.elapsedRealtime() - pauseOffset);
                    builder.setWhen(System.currentTimeMillis() - SystemClock.elapsedRealtime() + current.getBase()).setUsesChronometer(true).setContentText("").build();
                    notificationManager.notify(1, builder.build());
                    current.start();
                    running = true;

                    if(currentTimerSection.getType() == 2) {
                        actual.setBase(SystemClock.elapsedRealtime() - pauseOffset);
                        actual.start();
                    }
                } else if (timerStatus == 3) { //3=Status: Finished
                    vibrator.cancel();
                    currentTimerSection = getNextTimerSection(timer, currentTimerSection.getId());
                    current.stop();
                    actual.stop();
                    running = false;
                    actual.setFormat("%s");
                    actual.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.white));
                    if (currentTimerSection == null) {
                        notificationManager.cancel(1);
                        Toast.makeText(getApplicationContext(), R.string.match_finished, Toast.LENGTH_LONG).show();
                        intent = new Intent(getApplicationContext(), MainActivity.class);
                        getApplicationContext().startActivity(intent);
                    } else {
                        sectionName.setText(currentTimerSection.getName());
                        timerButton.setText(R.string.button_start);
                        timerStatus = 0;

                        checkHeadStart();
                        builder.setWhen(System.currentTimeMillis() - SystemClock.elapsedRealtime() + current.getBase()).setUsesChronometer(false).setContentText("Waiting for Next Section to start.").build();
                        notificationManager.notify(1, builder.build());
                    }
                }
            }
        });

        timerButton.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                if(timerStatus != 3) {
                    prev_timer_status = timerStatus;
                    timerStatus = 3;
                    timerButton.setText(R.string.button_end);
                    return true;
                } else {
                    timerStatus = prev_timer_status;
                    if(timerStatus == 1) {
                        timerButton.setText(R.string.button_pause);
                    } else if (timerStatus == 2) {
                        timerButton.setText(R.string.button_resume);
                    } else if (timerStatus == 0) {
                        timerButton.setText(R.string.button_start);
                    }
                    return true;
                }
            }
        });

        actual.setOnChronometerTickListener(new Chronometer.OnChronometerTickListener() {
            @Override
            public void onChronometerTick(Chronometer chronometer) {
                if(SystemClock.elapsedRealtime() - chronometer.getBase() >= currentTimerSection.getMinutes()*60000 + currentTimerSection.getSeconds()*1000 + currentTimerSection.getMinutesHeadStart()*60000 + currentTimerSection.getSecondsHeadStart()*1000 && chronometer.getCurrentTextColor() != ContextCompat.getColor(getApplicationContext(), R.color.red)) {
                    chronometer.setFormat("+%s");
                    chronometer.setBase(SystemClock.elapsedRealtime());
                    chronometer.setTextColor(ContextCompat.getColor(getApplicationContext(), R.color.red));
                    long[] timings = {0, 500, 500, 500, 500};
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                        vibrator.vibrate(VibrationEffect.createWaveform(timings, 0));
                    } else {
                        vibrator.vibrate(timings, 0);
                    }
                }
            }
        });
        current.setOnChronometerTickListener(new Chronometer.OnChronometerTickListener() {
            @Override
            public void onChronometerTick(Chronometer chronometer) {
                if(SystemClock.elapsedRealtime() - chronometer.getBase() >= currentTimerSection.getMinutes()*60000 + currentTimerSection.getSeconds()*1000 + currentTimerSection.getMinutesHeadStart()*60000 + currentTimerSection.getSecondsHeadStart()*1000 && timerStatus != 3) {
                    timerStatus = 3;
                    timerButton.setText(R.string.button_end);
                    current.stop();
                }
            }
        });
    }

    private void checkHeadStart() {
        if(currentTimerSection.isTimerHeadStart()) {
            current.setBase(SystemClock.elapsedRealtime() - currentTimerSection.getMinutesHeadStart()*60000 - currentTimerSection.getSecondsHeadStart()*1000);
            actual.setBase(SystemClock.elapsedRealtime() - currentTimerSection.getMinutesHeadStart()*60000 - currentTimerSection.getSecondsHeadStart()*1000);
        } else {
            current.setBase(SystemClock.elapsedRealtime());
            actual.setBase(SystemClock.elapsedRealtime());
        }
    }

    private static final long AMBIENT_INTERVAL_MS = TimeUnit.SECONDS.toMillis(1);
    //private static final long ACTIVE_INTERVAL_MS = TimeUnit.SECONDS.toMillis(1);
    //private static final int MSG_UPDATE_SCREEN = 0;
    private void refreshDisplayAndSetNextUpdate() {
        if (mAmbientController.isAmbient()) {
            // Implement data retrieval and update the screen for ambient mode
        } else {
            // Implement data retrieval and update the screen for interactive mode
        }
        long timeMs = System.currentTimeMillis();
        // Schedule a new alarm
        if (mAmbientController.isAmbient()) {
            // Calculate the next trigger time
            long delayMs = AMBIENT_INTERVAL_MS - (timeMs % AMBIENT_INTERVAL_MS);
            long triggerTimeMs = timeMs + delayMs;
            mAmbientUpdateAlarmManager.setExact(
                    AlarmManager.RTC_WAKEUP,
                    triggerTimeMs,
                    mAmbientUpdatePendingIntent);
        } else {
            //long delayMs = ACTIVE_INTERVAL_MS - (timeMs % ACTIVE_INTERVAL_MS);

            //mActiveModeUpdateHandler.removeMessages(MSG_UPDATE_SCREEN);
            //mActiveModeUpdateHandler.sendEmptyMessageDelayed(MSG_UPDATE_SCREEN, delayMs);
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        IntentFilter filter = new IntentFilter(AMBIENT_UPDATE_ACTION);
        registerReceiver(mAmbientUpdateBroadcastReceiver, filter);

        refreshDisplayAndSetNextUpdate();
    }

    @Override
    public void onPause() {
        super.onPause();
        unregisterReceiver(mAmbientUpdateBroadcastReceiver);
        mAmbientUpdateAlarmManager.cancel(mAmbientUpdatePendingIntent);
    }

    @Override
    public void onDestroy() {
        mAmbientUpdateAlarmManager.cancel(mAmbientUpdatePendingIntent);
        notificationManager.cancel(1);
        Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
        vibrator.cancel();
        super.onDestroy();
    }

    public TimerSection getFirstTimerSection(Timer timer) {
        List<TimerSection> timerSectionList = timer.getTimerSections();
        for (TimerSection t : timerSectionList) {
            if (t.id == 1) {
                return t;
            }
        }

        return null;
    }

    public TimerSection getNextTimerSection(Timer timer, int id) {
        List<TimerSection> timerSectionList = timer.getTimerSections();
        for(TimerSection t : timerSectionList) {
            if (t.id == id + 1) {
                return t;
            }
        }

        return null;
    }

    private class MyAmbientCallback extends AmbientModeSupport.AmbientCallback {
        /** Prepares the UI for ambient mode. */
        @Override
        public void onEnterAmbient(Bundle ambientDetails) {
            super.onEnterAmbient(ambientDetails);

            timerButton.setVisibility(View.INVISIBLE);
            Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
            vibrator.cancel();

            mIsLowBitAmbient =
                    ambientDetails.getBoolean(AmbientModeSupport.EXTRA_LOWBIT_AMBIENT, false);
            mDoBurnInProtection =
                    ambientDetails.getBoolean(AmbientModeSupport.EXTRA_BURN_IN_PROTECTION, false);

            /* Clears Handler queue (only needed for updates in active mode). */
            //mActiveModeUpdateHandler.removeMessages(MSG_UPDATE_SCREEN);

            /*
             * Following best practices outlined in WatchFaces API (keeping most pixels black,
             * avoiding large blocks of white pixels, using only black and white, and disabling
             * anti-aliasing, etc.)
             */

            if (mIsLowBitAmbient) {
                clock.getPaint().setAntiAlias(false);
                current.getPaint().setAntiAlias(false);
                actual.getPaint().setAntiAlias(false);
                timerButton.getPaint().setAntiAlias(false);
                label_actual.getPaint().setAntiAlias(false);
                label_current.getPaint().setAntiAlias(false);
                timerName.getPaint().setAntiAlias(false);
                sectionName.getPaint().setAntiAlias(false);
            }

            refreshDisplayAndSetNextUpdate();
        }

        @Override
        public void onUpdateAmbient() {
            super.onUpdateAmbient();

            if (mDoBurnInProtection) {
                int x = (int) (Math.random() * 2 * BURN_IN_OFFSET_PX - BURN_IN_OFFSET_PX);
                int y = (int) (Math.random() * 2 * BURN_IN_OFFSET_PX - BURN_IN_OFFSET_PX);
                timer_layout.setPadding(x, y, 0, 0);
            }
        }

        /** Restores the UI to active (non-ambient) mode. */
        @Override
        public void onExitAmbient() {
            super.onExitAmbient();

            timerButton.setVisibility(View.VISIBLE);
            Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
            vibrator.cancel();

            /* Clears out Alarms since they are only used in ambient mode. */
            mAmbientUpdateAlarmManager.cancel(mAmbientUpdatePendingIntent);


            if (mIsLowBitAmbient) {
                clock.getPaint().setAntiAlias(true);
                current.getPaint().setAntiAlias(true);
                actual.getPaint().setAntiAlias(true);
                timerButton.getPaint().setAntiAlias(true);
                label_actual.getPaint().setAntiAlias(true);
                label_current.getPaint().setAntiAlias(true);
                timerName.getPaint().setAntiAlias(true);
                sectionName.getPaint().setAntiAlias(true);
            }

            /* Reset any random offset applied for burn-in protection. */
            if (mDoBurnInProtection) {
                timer_layout.setPadding(0, 0, 0, 0);
            }

            refreshDisplayAndSetNextUpdate();
        }
    }
}
导入android.app.AlarmManager;
导入android.app.NotificationChannel;
导入android.app.NotificationManager;
导入android.app.pendingent;
导入android.content.BroadcastReceiver;
导入android.content.Context;
导入android.content.Intent;
导入android.content.IntentFilter;
导入android.os.*;
导入android.support.constraint.ConstraintLayout;
导入android.support.v4.app.FragmentActivity;
导入android.support.v4.content.ContextCompat;
导入android.support.wear.ambient.AmbientModeSupport;
导入android.util.Log;
导入android.view.view;
导入android.widget.Button;
导入android.widget.Chronometer;
导入android.widget.TextClock;
导入android.widget.TextView;
导入android.widget.Toast;
导入android.support.v4.app.NotificationCompat;
导入java.time.LocalDateTime;
导入java.util.List;
导入java.util.concurrent.TimeUnit;
公共类TimePractivity扩展碎片活动实现AmbientModeSupport.AmbientCallbackProvider{
@凌驾
public AmbientModeSupport.AmbientCallback getAmbientCallback(){
返回新的MyAmbientCallback();
}
私有静态最终字符串AMBIENT\u UPDATE\u ACTION=“de.jannisgoeing.sporttimerforwearos.ACTION.AMBIENT\u UPDATE”;
专用静态最终int BURN_IN_OFFSET_PX=10;
布尔误码;
布尔mDoBurnInProtection;
私有AlarmManager mAmbientUpdateAlarmManager;
私人悬挂式帐篷MambientUpdatePending帐篷;
专用广播接收器mAmbientUpdateBroadcastReceiver;
专用AmbientModeSupport.AmbientController-mAmbientController;
专用约束定时单元布局;
私人文本时钟;
私有文本视图timerName;
私有文本视图部分名称;
私人长暂停补偿;
私人意图;
私人定时器;
私人按钮时间按钮;
私有int timerStatus=0;
私有TimerSection currentTimerSection;
私有int prev_定时器_状态;
私有文本视图标签_当前;
私有文本视图标签_实际;
专用天文钟电流;
私人天文钟;
私有布尔运行;
私人通知经理通知经理;
@抑制警告(“弃用”)
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity\u计时器);
//启用“始终打开”
mAmbientController=AmbientModeSupport.attach(此);
mAmbientUpdateAlarmManager=
(AlarmManager)getSystemService(Context.ALARM\u服务);
意图环境更新内容=新意图(环境更新动作);
MambientUpdatePendingEvent=PendingEvent.getBroadcast(
这,0,AmbientUpdateContent,PendingContent.FLAG_UPDATE_CURRENT);
mAmbientUpdateBroadcastReceiver=新广播接收器(){
@凌驾
公共void onReceive(上下文、意图){
refreshDisplayAndSetNextUpdate();
}
};
最终可控震源=(可控震源)getSystemService(Context.可控震源\u服务);
notificationManager=getSystemService(notificationManager.class);
if(Build.VERSION.SDK\u INT>=Build.VERSION\u code.O){
notificationManager.createNotificationChannel(
新的通知通道(“计时器”、“计时器”、通知管理器。重要性高)
);
}
intent=this.getIntent();
if(intent.getExtras()==null){
Toast.makeText(this,R.string.error\u noProfilePassed,Toast.LENGTH\u LONG.show();
意图=新意图(此,MainActivity.class);
这一点。触觉(意图);
}否则{
timer=(timer)intent.getSerializableExtra(“timer”);
}
如果(计时器==null){
Toast.makeText(this,R.string.error_noValidTimerPassed,Toast.LENGTH_LONG).show();
意图=新意图(此,MainActivity.class);
这一点。触觉(意图);
}
计时器布局=findViewById(R.id.timer\u布局);
时钟=findViewById(R.id.textClock);
clock.setFormat24Hour(clock.getFormat24Hour());
timerName=findviewbyd(R.id.timerName);
timerName.setText(timer.getName());
电流=findViewById(R.id.计时电流);
实际值=findViewById(R.id.计时器实际值);
label_current=findViewById(R.id.labelCurrentTime);
label_actual=findViewById(R.id.labelActualTime);
currentTimerSection=getFirstTimerSection(计时器);
sectionName=findViewById(R.id.sectionName);
sectionName.setText(currentTimerSection.getName());
运行=错误;
意向停止意向=新意向(“de.jannisgoeing.sportstimerforwearos.STOP”);
PendingIntent stopPendingIntent=PendingIntent.getBroadcast(this,0,stopIntent,0);
意向启动=新意向(“de.jannisgoing.sporttimer for wearos.STARTPAUSE”);
潘丁基