简体   繁体   中英

How to launch an activity from a lockscreen widget, without unlocking?

I have a button on a lockscreen widget, and I'd like the button to launch an activity when pressed. If the screen is locked, I want the activity to appear over the lockscreen, without the user having to enter the PIN or pattern or whatever, and the lockscreen should reappear when the user leaves the activity.

I know about WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED , and my activity does appear over the lockscreen if I launch it manually using am start from an ADB shell. The problem is, when I press the button in the widget, it makes me enter the unlock PIN before it creates the activity at all.

I have this code in my widget provider:

@Override
public void onUpdate(final Context context, final AppWidgetManager appWidgetManager, final int[] appWidgetIds) {
    for (final int appWidgetId : appWidgetIds) {
        // Get the RemoteViews for controlling this widget instance.
        final RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.my_widget);

        // Construct an intent to launch the activity.
        final Intent intent = new Intent(context, MyActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        // Attach the intent to the widget's button.
        final PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
        views.setOnClickPendingIntent(R.id.my_button, pendingIntent);

        appWidgetManager.updateAppWidget(appWidgetId, views);
    }
}

And here's the code in MyActivity :

public MyActivity() {
    Log.d(TAG, "Activity instantiated");
}

@Override
protected void onCreate(final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Allow this activity to appear over the lock screen.
    final Window window = getWindow();
    window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);

    setContentView(R.layout.my_activity);
}

When I press the button in the widget, I'm prompted for the unlock PIN. The log message in the activity's constructor doesn't appear until after I enter the PIN, which means that Android is deciding to ask for the pin before the FLAG_SHOW_WHEN_LOCKED can have any effect.

Is there a way to tell Android that I want to launch the activity while the screen is still locked? Maybe a flag that I can set on my Intent or PendingIntent ?

You can use a broadcast intent and listen to it in your widget provider, then on the onRecieve method, start the activity intent, that's will not unlock your device but will launch your activity on foreground without requesting user to unlock.

Intent broadcastIntent = new Intent("com.yourapp.yourbroadcast");
widget.setOnClickPendingIntent(R.id.yourButton,  
                               PendingIntent.getBroadcast(ctxt, 0, broadcastIntent, PendingIntent.FLAG_UPDATE_CURRENT));

On your onRecieve(Context ctx, Intent intent) :

if (intent.getAction().equals("com.yourapp.yourbroadcast"))
{ 
       final Intent intent = new Intent(context, MyActivity.class);
       intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
       ctx.startActivity(intent) ;
}

In your Manifest:

<receiver
        android:name=".YourWidget"
        android:label="Your Widget description" >
        <intent-filter>
            <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
            <action android:name="com.yourpackage.widgetbroadcast" />
        </intent-filter>
        <meta-data
            android:name="android.appwidget.provider"
            android:resource="@xml/wisget_yourwidget" />
</receiver>

Your Widgetclass:

public class YourWidget extends AppWidgetProvider {
    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        for (int i = 0; i < appWidgetIds.length; i++) {
            int appWidgetId = appWidgetIds[i];      
            RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
            Intent intent = new Intent("com.yourpackage.widgetbroadcast");
            PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
            views.setOnClickPendingIntent(R.id.widget_yourlayout, pendingIntent);
            appWidgetManager.updateAppWidget(appWidgetId, views);
        }
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        super.onReceive(context, intent);
        if (intent.getAction().equals("com.yourpackage.widgetbroadcast")) {
            Intent intentStart = new Intent(context, MainActivity.class);           
            intentStart.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(intentStart);
        }
    }
}

In your MainActivity:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);        
    Window w = getWindow();
    w.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
    //Your code...
}

Make sure you set the Widow-Flag in the activity to FLAG_SHOW_WHEN_LOCKED and not to FLAG_DISMISS_KEYGUARD to keep the screen locked. This example will start the activity by clicking on the widget.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM