android wakelock

2023-05-16

1.android休眠控制锁

  powermanager.acquir(); 获取控制锁

 powermanager.release(); 释放控制锁

2.在powerManagerService中,有检测当前framework层中的wakelock锁的,并判断当前锁的状态。

 private void updateWakeLockSummaryLocked(int dirty) {
        if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_WAKEFULNESS)) != 0) {
            mWakeLockSummary = 0;

            final int numWakeLocks = mWakeLocks.size();
            for (int i = 0; i < numWakeLocks; i++) {
                final WakeLock wakeLock = mWakeLocks.get(i);
                switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
                    case PowerManager.PARTIAL_WAKE_LOCK:
                        if (!wakeLock.mDisabled) {
                            // We only respect this if the wake lock is not disabled.
                            mWakeLockSummary |= WAKE_LOCK_CPU;
                        }
                        break;
                    case PowerManager.FULL_WAKE_LOCK:
                        mWakeLockSummary |= WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_BUTTON_BRIGHT;
                        break;
                    case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
                        mWakeLockSummary |= WAKE_LOCK_SCREEN_BRIGHT;
                        break;
                    case PowerManager.SCREEN_DIM_WAKE_LOCK:
                        mWakeLockSummary |= WAKE_LOCK_SCREEN_DIM;
                        break;
                    case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
                        mWakeLockSummary |= WAKE_LOCK_PROXIMITY_SCREEN_OFF;
                        break;
                    case PowerManager.DOZE_WAKE_LOCK:
                        mWakeLockSummary |= WAKE_LOCK_DOZE;
                        break;
                    case PowerManager.DRAW_WAKE_LOCK:
                        mWakeLockSummary |= WAKE_LOCK_DRAW;
                        break;
                }
            }

            // Cancel wake locks that make no sense based on the current state.
            if (mWakefulness != WAKEFULNESS_DOZING) {
                mWakeLockSummary &= ~(WAKE_LOCK_DOZE | WAKE_LOCK_DRAW);
            }
            if (mWakefulness == WAKEFULNESS_ASLEEP
                    || (mWakeLockSummary & WAKE_LOCK_DOZE) != 0) {
                mWakeLockSummary &= ~(WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM
                        | WAKE_LOCK_BUTTON_BRIGHT);
                if (mWakefulness == WAKEFULNESS_ASLEEP) {
                    mWakeLockSummary &= ~WAKE_LOCK_PROXIMITY_SCREEN_OFF;
                }
            }

            // Infer implied wake locks where necessary based on the current state.
            if ((mWakeLockSummary & (WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM)) != 0) {
                if (mWakefulness == WAKEFULNESS_AWAKE) {
                    mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_STAY_AWAKE;
                } else if (mWakefulness == WAKEFULNESS_DREAMING) {
                    mWakeLockSummary |= WAKE_LOCK_CPU;
                }
            }
            if ((mWakeLockSummary & WAKE_LOCK_DRAW) != 0) {
                mWakeLockSummary |= WAKE_LOCK_CPU;
            }

            if (DEBUG_SPEW) {
                Slog.d(TAG, "updateWakeLockSummaryLocked: mWakefulness="
                        + PowerManagerInternal.wakefulnessToString(mWakefulness)
                        + ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary));
            }
        }
        // mWakeLockSummary = 0;
    }

系统会根据mWakeLockSummary 变量的值来判定当前的状态。

android o wake lock包括的类型如下:

    /**
     * Wake lock level: Ensures that the CPU is running; the screen and keyboard
     * backlight will be allowed to go off.
     */
    public static final int PARTIAL_WAKE_LOCK = 0x00000001;

    /**
     * Wake lock level: Ensures that the screen is on (but may be dimmed);
     * the keyboard backlight will be allowed to go off.
     * <p>
     * If the user presses the power button, then the {@link #SCREEN_DIM_WAKE_LOCK} will be
     * implicitly released by the system, causing both the screen and the CPU to be turned off.
     * Contrast with {@link #PARTIAL_WAKE_LOCK}.
     * </p>
     */
    @Deprecated
    public static final int SCREEN_DIM_WAKE_LOCK = 0x00000006;

    /**
     * Wake lock level: Ensures that the screen is on at full brightness;
     * the keyboard backlight will be allowed to go off.
     * <p>
     * If the user presses the power button, then the {@link #SCREEN_BRIGHT_WAKE_LOCK} will be
     * implicitly released by the system, causing both the screen and the CPU to be turned off.
     * Contrast with {@link #PARTIAL_WAKE_LOCK}.
     * </p>
     */
    @Deprecated
    public static final int SCREEN_BRIGHT_WAKE_LOCK = 0x0000000a;

    /**
     * Wake lock level: Ensures that the screen and keyboard backlight are on at
     * full brightness.
     * <p>
     * If the user presses the power button, then the {@link #FULL_WAKE_LOCK} will be
     * implicitly released by the system, causing both the screen and the CPU to be turned off.
     * Contrast with {@link #PARTIAL_WAKE_LOCK}.
     * </p>
     */
    @Deprecated
    public static final int FULL_WAKE_LOCK = 0x0000001a;

    /**
     * Wake lock level: Turns the screen off when the proximity sensor activates.
     * <p>
     * If the proximity sensor detects that an object is nearby, the screen turns off
     * immediately.  Shortly after the object moves away, the screen turns on again.
     * </p><p>
     * A proximity wake lock does not prevent the device from falling asleep
     * unlike {@link #FULL_WAKE_LOCK}, {@link #SCREEN_BRIGHT_WAKE_LOCK} and
     * {@link #SCREEN_DIM_WAKE_LOCK}.  If there is no user activity and no other
     * wake locks are held, then the device will fall asleep (and lock) as usual.
     * However, the device will not fall asleep while the screen has been turned off
     * by the proximity sensor because it effectively counts as ongoing user activity.
     * </p><p>
     * Since not all devices have proximity sensors, use {@link #isWakeLockLevelSupported}
     * to determine whether this wake lock level is supported.
     * </p><p>
     * Cannot be used with {@link #ACQUIRE_CAUSES_WAKEUP}.
     * </p>
     */
    public static final int PROXIMITY_SCREEN_OFF_WAKE_LOCK = 0x00000020;

    /**
     * Wake lock level: Put the screen in a low power state and allow the CPU to suspend
     * if no other wake locks are held.
     * <p>
     * This is used by the dream manager to implement doze mode.  It currently
     * has no effect unless the power manager is in the dozing state.
     * </p>
     * {@hide}
     */
    public static final int DOZE_WAKE_LOCK = 0x00000040;

    /**
     * Wake lock level: Keep the device awake enough to allow drawing to occur.
     * <p>
     * This is used by the window manager to allow applications to draw while the
     * system is dozing.  It currently has no effect unless the power manager is in
     * the dozing state.
     * </p>
     * {@hide}
     */
    public static final int DRAW_WAKE_LOCK = 0x00000080;

    /**
     * Mask for the wake lock level component of a combined wake lock level and flags integer.
     *
     * @hide
     */
    public static final int WAKE_LOCK_LEVEL_MASK = 0x0000ffff;

    /**
     * Wake lock flag: Turn the screen on when the wake lock is acquired.
     * <p>
     * Normally wake locks don't actually wake the device, they just cause
     * the screen to remain on once it's already on.  Think of the video player
     * application as the normal behavior.  Notifications that pop up and want
     * the device to be on are the exception; use this flag to be like them.
     * </p>
     */
    public static final int ACQUIRE_CAUSES_WAKEUP = 0x10000000;

    /**
     * Wake lock flag: When this wake lock is released, poke the user activity timer
     * so the screen stays on for a little longer.
     * <p>
     * Will not turn the screen on if it is not already on.
     * See {@link #ACQUIRE_CAUSES_WAKEUP} if you want that.
     * </p>
     */
    public static final int ON_AFTER_RELEASE = 0x20000000;

    /**
     * Wake lock flag: This wake lock is not important for logging events.  If a later
     * wake lock is acquired that is important, it will be considered the one to log.
     * @hide
     */
    public static final int UNIMPORTANT_FOR_LOGGING = 0x40000000;

 

在updateSuspendBlockerLocked函数中,首先会判断mWakeLockSummary的状态,确定系统是否要进入autosuspend模式。

在调用 setHalAutoSuspendModeLocked(true);

// Summarizes the state of all active wakelocks.
    private static final int WAKE_LOCK_CPU = 1 << 0;
    private static final int WAKE_LOCK_SCREEN_BRIGHT = 1 << 1;
    private static final int WAKE_LOCK_SCREEN_DIM = 1 << 2;
    private static final int WAKE_LOCK_BUTTON_BRIGHT = 1 << 3;
    private static final int WAKE_LOCK_PROXIMITY_SCREEN_OFF = 1 << 4;
    private static final int WAKE_LOCK_STAY_AWAKE = 1 << 5; // only set if already awake
    private static final int WAKE_LOCK_DOZE = 1 << 6;
    private static final int WAKE_LOCK_DRAW = 1 << 7;
/**
     * Updates the suspend blocker that keeps the CPU alive.
     *
     * This function must have no other side-effects.
     */
    private void updateSuspendBlockerLocked() {
        final boolean needWakeLockSuspendBlocker = ((mWakeLockSummary & WAKE_LOCK_CPU) != 0);
        final boolean needDisplaySuspendBlocker = needDisplaySuspendBlockerLocked();
        final boolean autoSuspend = !needDisplaySuspendBlocker;
        final boolean interactive = mDisplayPowerRequest.isBrightOrDim();
        Slog.d(TAG, "####3updateSuspendBlockerLocked:"+ autoSuspend+ " ,"+mDecoupleHalAutoSuspendModeFromDisplayConfig);
        // Disable auto-suspend if needed.
        // FIXME We should consider just leaving auto-suspend enabled forever since
        // we already hold the necessary wakelocks.
        if (!autoSuspend && mDecoupleHalAutoSuspendModeFromDisplayConfig) {
            setHalAutoSuspendModeLocked(false);
        }
        ...
        ...

         // mWakeLockSuspendBlocker.release();
        // mHoldingWakeLockSuspendBlocker = false;
        // Enable auto-suspend if needed.
        if (autoSuspend && mDecoupleHalAutoSuspendModeFromDisplayConfig) {
            setHalAutoSuspendModeLocked(true);
        }
}

3.android 自动超时休眠

在函数updateUserActivitySummaryLocked中,

 nextTimeout = mLastUserActivityTime+ screenOffTimeout - screenDimDuration;

nextTimeout 是屏幕自动黑屏的超时时间,当从系统开机的相对时间到了的时候,调用 sendMessageAtTime函数发送消息,

 if (mUserActivitySummary != 0 && nextTimeout >= 0) {
                    Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY_TIMEOUT);
                    msg.setAsynchronous(true);
                    mHandler.sendMessageAtTime(msg, nextTimeout);
                    Slog.d(TAG,"###send MSG_USER_ACTIVITY_TIMEOUT message\n");
                }

 

  /**
     * Updates the value of mUserActivitySummary to summarize the user requested
     * state of the system such as whether the screen should be bright or dim.
     * Note that user activity is ignored when the system is asleep.
     *
     * This function must have no other side-effects.
     */
    private void updateUserActivitySummaryLocked(long now, int dirty) {
        // Update the status of the user activity timeout timer.
        if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY
                | DIRTY_WAKEFULNESS | DIRTY_SETTINGS)) != 0) {
            mHandler.removeMessages(MSG_USER_ACTIVITY_TIMEOUT);

            long nextTimeout = 0;
            if (mWakefulness == WAKEFULNESS_AWAKE
                    || mWakefulness == WAKEFULNESS_DREAMING
                    || mWakefulness == WAKEFULNESS_DOZING) {
                final int sleepTimeout = getSleepTimeoutLocked();
                int screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout);
                final int screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);
                final boolean userInactiveOverride = mUserInactiveOverrideFromWindowManager;
                Slog.d(TAG,"now:"+ TimeUtils.formatUptime(now) +" sleepTimeout:"+ TimeUtils.formatUptime(sleepTimeout) + "screenOffTimeout:"+ TimeUtils.formatUptime(screenOffTimeout) + 
                    "screenDimDuration:"+ TimeUtils.formatUptime(screenDimDuration) +"mLastWakeTime:"+ TimeUtils.formatUptime(mLastWakeTime));
                mUserActivitySummary = 0;
                if (mLastUserActivityTime >= mLastWakeTime) {
                    nextTimeout = mLastUserActivityTime
                            + screenOffTimeout - screenDimDuration;
                    if (now < nextTimeout) {
                        mUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;
                    } else {
                        nextTimeout = mLastUserActivityTime + screenOffTimeout;
                        if (now < nextTimeout) {
                            mUserActivitySummary = USER_ACTIVITY_SCREEN_DIM;
                        }
                    }
                }
                if (mUserActivitySummary == 0
                        && mLastUserActivityTimeNoChangeLights >= mLastWakeTime) {
                    nextTimeout = mLastUserActivityTimeNoChangeLights + screenOffTimeout;
                    if (now < nextTimeout) {
                        if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_BRIGHT
                                || mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_VR) {
                            mUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;
                        } else if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
                            mUserActivitySummary = USER_ACTIVITY_SCREEN_DIM;
                        }
                    }
                }

                if (mUserActivitySummary == 0) {
                    if (sleepTimeout >= 0) {
                        final long anyUserActivity = Math.max(mLastUserActivityTime,
                                mLastUserActivityTimeNoChangeLights);
                        if (anyUserActivity >= mLastWakeTime) {
                            nextTimeout = anyUserActivity + sleepTimeout;
                            if (now < nextTimeout) {
                                mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;
                            }
                        }
                    } else {
                        mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;
                        nextTimeout = -1;
                    }
                }

                if (mUserActivitySummary != USER_ACTIVITY_SCREEN_DREAM && userInactiveOverride) {
                    if ((mUserActivitySummary &
                            (USER_ACTIVITY_SCREEN_BRIGHT | USER_ACTIVITY_SCREEN_DIM)) != 0) {
                        // Device is being kept awake by recent user activity
                        if (nextTimeout >= now && mOverriddenTimeout == -1) {
                            // Save when the next timeout would have occurred
                            mOverriddenTimeout = nextTimeout;
                        }
                    }
                    mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM;
                    nextTimeout = -1;
                }

                if (mUserActivitySummary != 0 && nextTimeout >= 0) {
                    Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY_TIMEOUT);
                    msg.setAsynchronous(true);
                    mHandler.sendMessageAtTime(msg, nextTimeout);
                    Slog.d(TAG,"###send MSG_USER_ACTIVITY_TIMEOUT message\n");
                }
            } else {
                mUserActivitySummary = 0;
            }

            if (DEBUG_SPEW) {
                Slog.d(TAG, "updateUserActivitySummaryLocked: mWakefulness="
                        + PowerManagerInternal.wakefulnessToString(mWakefulness)
                        + ", mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary)
                        + ", nextTimeout=" + TimeUtils.formatUptime(nextTimeout));
            }
        }
    }

  当收到消息后,调用函数handleUserActivityTimeout,接着再调用updatePowerStateLocked函数。

 

 /**
     * Called when a user activity timeout has occurred.
     * Simply indicates that something about user activity has changed so that the new
     * state can be recomputed when the power state is updated.
     *
     * This function must have no other side-effects besides setting the dirty
     * bit and calling update power state.  Wakefulness transitions are handled elsewhere.
     */
    private void handleUserActivityTimeout() { // runs on handler thread
        synchronized (mLock) {
            if (DEBUG_SPEW) {
                Slog.d(TAG, "handleUserActivityTimeout");
            }
            Slog.d(TAG, "####handleUserActivityTimeout");
            mDirty |= DIRTY_USER_ACTIVITY;
            updatePowerStateLocked();
        }
    }

 

 

在updatePowerStateLocked()中,当检测到mDirty = DIRTY_USER_ACTIVITY时,在函数updateWakefulnessLocked()中会执行

goToSleepNoUpdateLocked(),r接着调用 setWakefulnessLocked(WAKEFULNESS_DOZING, reason);设置mWakefulness=WAKEFULNESS_DOZING;

/**
     * Updates the global power state based on dirty bits recorded in mDirty.
     *
     * This is the main function that performs power state transitions.
     * We centralize them here so that we can recompute the power state completely
     * each time something important changes, and ensure that we do it the same
     * way each time.  The point is to gather all of the transition logic here.
     */
    private void updatePowerStateLocked() {
        if (!mSystemReady || mDirty == 0) {
            return;
        }
        Slog.d(TAG, "###updatePowerStateLocked\n");
        if (!Thread.holdsLock(mLock)) {
            Slog.wtf(TAG, "Power manager lock was not held when calling updatePowerStateLocked");
        }

        Trace.traceBegin(Trace.TRACE_TAG_POWER, "updatePowerState");
        try {
            // Phase 0: Basic state updates.
            updateIsPoweredLocked(mDirty);
            updateStayOnLocked(mDirty);
            updateScreenBrightnessBoostLocked(mDirty);

            // Phase 1: Update wakefulness.
            // Loop because the wake lock and user activity computations are influenced
            // by changes in wakefulness.
            final long now = SystemClock.uptimeMillis();
            int dirtyPhase2 = 0;
            for (;;) {
                int dirtyPhase1 = mDirty;
                dirtyPhase2 |= dirtyPhase1;
                mDirty = 0;
                Slog.d(TAG,"dirtyPhase1:"+ dirtyPhase1 + " dirtyPhase2:"+ dirtyPhase2);
                updateWakeLockSummaryLocked(dirtyPhase1);
                updateUserActivitySummaryLocked(now, dirtyPhase1);
                if (!updateWakefulnessLocked(dirtyPhase1)) {
                    break;
                }
            }

            // Phase 2: Update display power state.
            boolean displayBecameReady = updateDisplayPowerStateLocked(dirtyPhase2);

            // Phase 3: Update dream state (depends on display ready signal).
            updateDreamLocked(dirtyPhase2, displayBecameReady);

            // Phase 4: Send notifications, if needed.
            finishWakefulnessChangeIfNeededLocked();

            // Phase 5: Update suspend blocker.
            // Because we might release the last suspend blocker here, we need to make sure
            // we finished everything else first!
            updateSuspendBlockerLocked();
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_POWER);
        }
    }
 private boolean goToSleepNoUpdateLocked(long eventTime, int reason, int flags, int uid) {
    .....
try {
            switch (reason) {
                case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN:
                    Slog.i(TAG, "Going to sleep due to device administration policy "
                            + "(uid " + uid +")...");
                    break;
                case PowerManager.GO_TO_SLEEP_REASON_TIMEOUT:
                    Slog.i(TAG, "Going to sleep due to screen timeout (uid " + uid +")...");
                    break;
                case PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH:
                    Slog.i(TAG, "Going to sleep due to lid switch (uid " + uid +")...");
                    break;
                case PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON:
                    Slog.i(TAG, "Going to sleep due to power button (uid " + uid +")...");
                    break;
                case PowerManager.GO_TO_SLEEP_REASON_SLEEP_BUTTON:
                    Slog.i(TAG, "Going to sleep due to sleep button (uid " + uid +")...");
                    break;
                case PowerManager.GO_TO_SLEEP_REASON_HDMI:
                    Slog.i(TAG, "Going to sleep due to HDMI standby (uid " + uid +")...");
                    break;
                default:
                    Slog.i(TAG, "Going to sleep by application request (uid " + uid +")...");
                    reason = PowerManager.GO_TO_SLEEP_REASON_APPLICATION;
                    break;
            }

            mLastSleepTime = eventTime;
            mSandmanSummoned = true;
            setWakefulnessLocked(WAKEFULNESS_DOZING, reason);

.....
}

在 updatePowerStateLocked中的updateDreamLocked函数,通过发送消息MSG_SANDMAN,执行reallyGoToSleepNoUpdateLocked(),

 // Phase 3: Update dream state (depends on display ready signal).
            updateDreamLocked(dirtyPhase2, displayBecameReady);
/**
     * Determines whether to post a message to the sandman to update the dream state.
     */
    private void updateDreamLocked(int dirty, boolean displayBecameReady) {
        if ((dirty & (DIRTY_WAKEFULNESS
                | DIRTY_USER_ACTIVITY
                | DIRTY_WAKE_LOCKS
                | DIRTY_BOOT_COMPLETED
                | DIRTY_BOOT_IPO
                | DIRTY_SETTINGS
                | DIRTY_IS_POWERED
                | DIRTY_STAY_ON
                | DIRTY_PROXIMITY_POSITIVE
                | DIRTY_BATTERY_STATE)) != 0 || displayBecameReady) {
            if (mDisplayReady) {
                scheduleSandmanLocked();
            }
        }
    }

    private void scheduleSandmanLocked() {
        if (!mSandmanScheduled) {
            mSandmanScheduled = true;
            Message msg = mHandler.obtainMessage(MSG_SANDMAN);
            msg.setAsynchronous(true);
            mHandler.sendMessage(msg);
        }
    }


private void handleSandman() { 
.....
.....
  reallyGoToSleepNoUpdateLocked(SystemClock.uptimeMillis(), Process.SYSTEM_UID);
  updatePowerStateLocked();
....
}

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

android wakelock 的相关文章

  • 如何从android ble扫描结果中获取CRC?

    我每次都从 ble 设备收到 62 字节的扫描结果 使用下面的回调代码获取扫描结果 我可以获取 RSSI 但无法获取 CRC 或者 获取一帧的CRC的逻辑是什么 来自 ble 设备的数据格式 如数据包标头 广告数据 CRC RSSI 如何从
  • 模拟器中 Google Wear 上的语音识别器没有语音输入

    我试图使用 Google Wear 网站上的自由形式语音输入 在 hello world 示例中 我刚刚添加了对 textView 的单击 它确实从语音意图中调出 立即发言 活动 但模拟器无法检测到我的麦克风发出的任何声音 我使用的是 Ma
  • Android:如何暂停和恢复可运行线程?

    我正在使用 postDelayed 可运行线程 当我按下按钮时 我需要暂停并恢复该线程 请任何人帮助我 这是我的主题 protected void animation music6 music4 postDelayed new Runnab
  • Android中将JSON数据存储到本地数据库

    好的 我创建了一个应用程序 它使用 JSON 从我的服务器检索数据 现在我想将检索到的数据存储在手机的本地存储 数据库中 我该怎么做 我是android编程新手 这是我从服务器收到的 JSON messages id 44 issender
  • 如何在 Android 应用程序中隐藏 Flutterwave API 密钥

    我正在构建一个 Android 应用程序 目前正在将 Flutterwave 集成到我的应用程序中以进行支付 建议我永远不要将 Flutterwave API 密钥放在我的应用程序上 那么我该如何隐藏这些键呢 我正在使用 Retrofit
  • 无法在 Android Studio 中导出签名的 APK

    当我使用keytool list keystore path to keyfile jks并提供我的密码 我可以看到那里的条目 但是当我在尝试使用相同的密码生成签名的 APK 时使用相同的密码时 我收到错误 无法加载密钥库 密钥库被篡改 或
  • 4 天后,应用仍未在 Google Play 搜索中编入索引

    我已经在 4 天前在 google play 上发布了我的第一个应用程序 语音到短信 但我仍然无法通过其名称或开发人员名称在搜索中找到我的应用程序 我只能通过包名称或真实应用程序名称 但不带空格 找到我的应用程序 VoiceToSMS 链接
  • relativelayout导致动画不起作用?

    我有一个活动 其布局仅包含一个 VideoView 这是 XML
  • Play 商店中的应用描述更新

    我想更新应用程序的描述以及 Play 商店上的屏幕截图 但应用程序保持相同 即相同的版本号 我不想发布新应用程序 因为应用程序中没有任何更改 这可能吗 谷歌也会要求更新应用程序吗 您可以更新描述 也可以更改屏幕截图 您的应用程序将保持不变
  • 什么是 Android 测试协调器?

    谷歌最近发布了Android测试支持库1 0 读完后overview https android developers googleblog com 2017 07 android testing support library 10 is
  • 在 Android 中加密/解密字符串的简单方法

    我的问题是如何加密String String AndroidId Override public void onCreate Bundle savedInstanceState super onCreate savedInstanceSta
  • 如何在android中的谷歌地图上聚焦标记

    我只是想知道我们是否可以关注 Android 应用程序中添加的标记 如果是 怎么办 或者有没有其他方法可以完成这项任务 可以说我使用下面的代码添加了一个标记 map addMarker new MarkerOptions title tit
  • 如何在 60 分钟后删除共享首选项

    我想存储登录数据 但希望在 60 分钟后删除该数据 执行此操作的正确方法是什么 在这 60 分钟内可以关闭 停止 打开应用程序 我不想使用内部数据库 这是我的访问代码SharedPreferences sharedpreferences g
  • Android 认为我没有关闭数据库!为什么?

    我有一个 SQLiteDatabase 数据成员 我在 onCreate 中初始化它 并在 onPause onStop 和 onDestroy 中调用 close 它在 onResume 中重新初始化 它似乎运行得很好 但当我查看调试器时
  • AndEngine MenuScene - 无法单击按钮

    我有一个关于 android 和 andengine 的小问题 这是我的主菜单的源代码 AbstractScene is extending Scene public class MainMenuScene extends Abstract
  • 如何在同一设备上运行的 Android 应用程序之间传输文件?

    我正在编写一个与 RESTful 服务交互的 Android 应用程序 该 Web 服务本质上是一个文件系统 并提供元数据以及对文件的 CRUD 访问 我的应用程序检索元数据 并通过ContentProvider 我需要添加与我的应用程序在
  • 我在 android studio 中使用 kotlin 时出现错误

    为什么会出现这个错误 09 12 16 36 31 502 1886 1886 com getloction nourmedhat smartgate getlocation E AndroidRuntime 致命异常 main 进程 co
  • Android Google Map V2:如何在单击另一个标记时更改先前单击的标记的图标

    更新 我通过添加 previousMarker 对象解决了性能问题 因此 只有先前单击的标记将被删除并替换为默认图标 但是 当我单击标记时 信息窗口仍然不显示 我有一个地图视图并在上面设置了一些标记 我想要的是 当我单击一个标记时 它将其图
  • Android计算两个日期之间的天数

    我编写了以下代码来查找两个日期之间的天数 startDateValue new Date startDate endDateValue new Date endDate long diff endDateValue getTime star
  • 动态更改按钮上的图像视图

    在我的应用程序中 我有按钮和ImageView 当我按下按钮时我想改变ImageView 我的可绘制文件夹中有 5 张图像 按下按钮时 ImageView 根据按钮单击一张一张地更改图像 我想要它的解决方案 感谢任何可以提供帮助的人 维护一

随机推荐