4

我使用BroadcastReceiver接收來自AlarmManager的廣播。在接收器中,我開始了兩項活動。一個活動是由URI這樣的開始,是一個第三方應用:Android的鎖屏上的URI的startActivity Nougat

// Open spotify 
Intent spotify = new Intent(Intent.ACTION_VIEW, Uri.parse(song)); 
spotify.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 

try { 
    context.startActivity(spotify); 
} catch (ActivityNotFoundException e) { 
    status = Status.SPOTIFY_NOT_INSTALLED; 
} 

從那以後,我開始,使用AlarmManager又屬於應用程序與5秒的延遲的另一項活動:

public static void setExact(
     Context context, PendingIntent pendingIntent, long time 
) { 

    AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) 
     am.setExact(AlarmManager.RTC_WAKEUP, time, pendingIntent); 
    else 
     am.set(AlarmManager.RTC_WAKEUP, time, pendingIntent); 

} 

public static void setExactDelay(
     Context context, PendingIntent pendingIntent, long delay 
) { 
    setExact(context, pendingIntent, System.currentTimeMillis() + delay); 
} 

    PendingIntent pendingIntent = AlarmPlayActivity.makePendingIntent(context, alarm, status, startTime); 
    AlarmSet.setExactDelay(context, pendingIntent, 5000); 

第二項活動按預期在5秒後開始。然而,第一項活動僅在設備解鎖時開始。如果設備已鎖定,則無法在Android Nougat(7.0)上啓動。這種情況即使鎖不能通過密碼,模式等進行保護。即使使用安全鎖,這也可用於早期的Android版本。

有沒有一種方法可以在不需要屏幕的情況下啓動第一個活動?

編輯:我試過使用以下IntentService

public class AlarmService extends IntentService { 

    static final int NOTIFICATION_ID = 1; 

    public AlarmService() { 
     super("AlarmService"); 
    } 

    public static Intent makeIntent(Context context, Alarm alarm, AlarmReceiver.Status status, long startTime) { 

     Intent intent = IntentFactory.alarmPlayIntent(alarm, status, startTime); 
     intent.setClass(context, AlarmService.class); 

     return intent; 

    } 

    private static void sleep(long time) { 
     try { 
      Thread.sleep(time); 
     } catch (InterruptedException e) { 
      // Nothing 
     } 
    } 

    @Override 
    protected void onHandleIntent(Intent intent) { 

     // Acquire Wakelock immediately 

     PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); 

     PowerManager.WakeLock wakeLock = pm.newWakeLock(
       PowerManager.FULL_WAKE_LOCK | 
       PowerManager.ACQUIRE_CAUSES_WAKEUP | 
       PowerManager.ON_AFTER_RELEASE, 
       "AlarmServiceWakeLock" 
     ); 

     wakeLock.acquire(); 

     KeyguardManager.KeyguardLock lock = ((KeyguardManager) getSystemService(Activity.KEYGUARD_SERVICE)).newKeyguardLock(KEYGUARD_SERVICE); 
     lock.disableKeyguard(); 

     // Get intent data 

     final Alarm alarm = IntentFactory.getAlarm(intent); 
     AlarmReceiver.Status status = IntentFactory.getStatus(intent); 
     final long startTime = IntentFactory.getStartTime(intent, 0); 

     // Get a random song for this alarm 

     AlarmDatabase db = AlarmDatabase.getInstance(this); 
     Song song = db.getRandomSong(alarm); 

     String songName = song == null ? "backup sound" : song.getName(); 

     // Start a foreground notification 

     Notification notification = new NotificationCompat.Builder(this) 
       .setContentTitle(getText(R.string.alarm_starting_notification_title)) 
       .setContentText(getString(
         R.string.alarm_starting_notification_message, alarm.getName(), songName 
       )) 
       .setSmallIcon(R.drawable.ic_launcher) 
       .setPriority(NotificationCompat.PRIORITY_MAX) 
       .build(); 

     startForeground(NOTIFICATION_ID, notification); 

     // Potentially open Spotify if we can 

     if (song != null) { 

      // Open spotify 

      Intent spotify = new Intent(Intent.ACTION_VIEW, Uri.parse(song.getUri())); 
      spotify.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); 

      try { 
       startActivity(spotify); 
      } catch (ActivityNotFoundException e) { 
       status = AlarmReceiver.Status.SPOTIFY_NOT_INSTALLED; 
      } 

     } else 
      status = AlarmReceiver.Status.NO_SONGS; 

     // Start play activity in 10 seconds, giving Spotify some chance to load up. 

     sleep(10); 
     startActivity(AlarmPlayActivity.makeIntent(this, alarm, status, startTime)); 

     // Keep alive for 5 more seconds 
     sleep(5); 

     // Stop notification 
     stopForeground(true); 

     // Release wakelock 
     wakeLock.release(); 


    } 

} 
+0

我想我可以創建一個特殊的'Activity',目的是保持裝置解鎖了一夜,直到警報亮起,但就是遠非理想。 –

+0

既然開展了自己的活動,爲什麼不開展一個簡單地激發你意圖的活動呢? – natario

+1

看起來像[here](http://stackoverflow.com/a/32511496/4069913)。試試'setAlarmclock'? –

回答

2

我經歷了同樣的問題,我覺得Intent.ACTION_VIEW不工作,直到你解開的,因爲安全的原因,屏幕:當設備處於清醒和解鎖,但有當設備被鎖定沒有運氣它的工作原理。

同樣問題討論here也。您還可以檢查此link

+1

我認爲你是對的。從最近的Android版本開始,我無法做到這一點,我懷疑Android開發者會改變這種行爲。我將不得不找到一個完全不同的解決方案。不幸的是,尼克弗里斯克爾的回答沒有奏效。 –

1

你必須使用先進的最新方法: 要麼 am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, nexttime, pendingintent);

am.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, nexttime, pendingintent);

不要忘記設置你的我喚醒模式: 開始:

PowerManager pm = (PowerManager) ctx.getSystemService(Context.POWER_SERVICE); 
      wakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | 
        PowerManager.ACQUIRE_CAUSES_WAKEUP | 
        PowerManager.ON_AFTER_RELEASE, A_.APPNAME + Integer.toString(index)); 
     if (wakeLock != null && wakeLock.isHeld()){ 
      wakeLock.acquire(); 
     } 

釋放:

wakeLock.release();

你可以設置你的活動爲前景(在鎖屏) 說明如下: https://stackoverflow.com/a/23611199/1979882

import android.view.Window; 
import android.view.WindowManager.LayoutParams; 


Window window = this.getWindow(); 
window.addFlags(LayoutParams.FLAG_DISMISS_KEYGUARD); 
window.addFlags(LayoutParams.FLAG_SHOW_WHEN_LOCKED); 
window.addFlags(LayoutParams.FLAG_TURN_SCREEN_ON); 

如下圖所示,那麼也可以開始你的活動:

https://stackoverflow.com/a/6468575/1979882

@Override 
    public void onReceive(Context context, Intent intent) { 
     //start activity 
     Intent i = new Intent(); 
     i.setClassName("com.test", "com.test.MainActivity"); 
     i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
     context.startActivity(i); 
    } 
1

Instea d直接從接收器啓動您的Spotify活動,請讓接收器從您的應用程序啓動Service

裏面的服務,獲得您激活鎖定,然後開始一個前景通知(建notificationNotificationCompat.Builder然後用startForeground(mId, notification);,該通知將保持服務活着的情況下,牛軋糖,否則停止。

然後從服務中激發您的Spotify Intent,然後殺掉服務,前臺通知和喚醒鎖。這對我來說很有用,可以避免像你所面臨的討厭的牛軋糖問題。希望這可以幫助!

+0

謝謝。今天我會嘗試這種方法,如果它有效,就獎勵賞金。 –

+0

不幸的是,這不適合我。我將發佈我在問題中使用的'IntentService'。它實際上會導致任何現有Spotify通知從鎖定屏幕中刪除,然後不會打開Spotify。它在設備喚醒和解鎖時工作。 –

+0

我剛剛提供了編輯。 –