微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

android – 是否可以在锁定屏幕上创建像Google Play音乐这样的小部件?

我正在开发一个音乐播放器.我有一个可在家庭和锁定屏幕上工作的小部件.我不想让用户选择在锁定屏幕上放置或删除小部件.

我的目标是:

>窗口小部件会自动显示在主机锁定屏幕上,删除作为时间日期窗口小部件或放置它的窗口小部件.
>始终如一地管理MusicService和Widget. (当我离开音乐播放器时,从锁定屏幕清除小部件.

这正是我的galaxy Nexus(或许多其他手机)上的Google Play音乐小部件.这可能吗?是否有可能我需要一些不是小工具的东西,比如自定义锁屏

最佳答案
好吧,解决方案很简单,不要使用任何小部件,只需使用RemoteControlClientCompat类.这是我的lockScreenControls()方法代码,每当我想显示这种类型的控件时,我都会调用它.

private void lockScreenControls() {

        // Use the media button APIs (if available) to register ourselves for media button
        // events

        MediaButtonHelper.registerMediaButtonEventReceiverCompat(mAudioManager,mMediaButtonReceiverComponent);
        // Use the remote control APIs (if available) to set the playback state
        if (mRemoteControlClientCompat == null) {
            Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON);
            intent.setComponent(mMediaButtonReceiverComponent);
            mRemoteControlClientCompat = new RemoteControlClientCompat(PendingIntent.getbroadcast(this /*context*/,0 /*requestCode,ignored*/,intent /*intent*/,0 /*flags*/));
            RemoteControlHelper.registerRemoteControlClient(mAudioManager,mRemoteControlClientCompat);
        }
        mRemoteControlClientCompat.setPlaybackState(RemoteControlClient.PLAYSTATE_PLAYING);
        mRemoteControlClientCompat.setTransportControlFlags(
                RemoteControlClient.FLAG_KEY_MEDIA_PAUSE |
                RemoteControlClient.FLAG_KEY_MEDIA_PREVIoUS |
                RemoteControlClient.FLAG_KEY_MEDIA_NEXT |
                RemoteControlClient.FLAG_KEY_MEDIA_STOP);

        //update remote controls
        mRemoteControlClientCompat.editMetadata(true)
                .putString(MediaMetadataRetriever.MetaDATA_KEY_ARTIST,"NombreArtista")
                .putString(MediaMetadataRetriever.MetaDATA_KEY_ALBUM,"Titulo Album")
                .putString(MediaMetadataRetriever.MetaDATA_KEY_TITLE,nombreCancion)
                //.putLong(MediaMetadataRetriever.MetaDATA_KEY_DURATION,playingItem.getDuration())
                        // Todo: fetch real item artwork
                .putBitmap(RemoteControlClientCompat.MetadataEditorCompat.MetaDATA_KEY_ARTWORK,getalbumart())
                .apply();
        }
    }

***********编辑************

RemoteControlClientCompat类:

@SuppressWarnings({"rawtypes","unchecked"})
public class RemoteControlClientCompat {

private static final String TAG = "RemoteControlCompat";

private static Class sRemoteControlClientClass;

// RCC short for RemoteControlClient
private static Method sRCCEditMetadataMethod;
private static Method sRCCSetPlayStateMethod;
private static Method sRCCSetTransportControlFlags;

private static boolean sHasRemoteControlAPIs = false;

static {
    try {
        ClassLoader classLoader = RemoteControlClientCompat.class.getClassLoader();
        sRemoteControlClientClass = getActualRemoteControlClientClass(classLoader);
        // dynamically populate the playstate and flag values in case they change
        // in future versions.
        for (Field field : RemoteControlClientCompat.class.getFields()) {
            try {
                Field realField = sRemoteControlClientClass.getField(field.getName());
                Object realValue = realField.get(null);
                field.set(null,realValue);
            } catch (NoSuchFieldException e) {
                Log.w(TAG,"Could not get real field: " + field.getName());
            } catch (IllegalArgumentException e) {
                Log.w(TAG,"Error trying to pull field value for: " + field.getName()
                        + " " + e.getMessage());
            } catch (illegalaccessexception e) {
                Log.w(TAG,"Error trying to pull field value for: " + field.getName()
                        + " " + e.getMessage());
            }
        }

        // get the required public methods on RemoteControlClient
        sRCCEditMetadataMethod = sRemoteControlClientClass.getmethod("editMetadata",boolean.class);
        sRCCSetPlayStateMethod = sRemoteControlClientClass.getmethod("setPlaybackState",int.class);
        sRCCSetTransportControlFlags = sRemoteControlClientClass.getmethod(
                "setTransportControlFlags",int.class);

        sHasRemoteControlAPIs = true;
    } catch (ClassNotFoundException e) {
        // Silently fail when running on an OS before ICS.
    } catch (NoSuchMethodException e) {
        // Silently fail when running on an OS before ICS.
    } catch (IllegalArgumentException e) {
        // Silently fail when running on an OS before ICS.
    } catch (SecurityException e) {
        // Silently fail when running on an OS before ICS.
    }
}

public static Class getActualRemoteControlClientClass(ClassLoader classLoader)
        throws ClassNotFoundException {
    return classLoader.loadClass("android.media.RemoteControlClient");
}

private Object mActualRemoteControlClient;

public RemoteControlClientCompat(PendingIntent pendingIntent) {
    if (!sHasRemoteControlAPIs) {
        return;
    }
    try {
        mActualRemoteControlClient =
                sRemoteControlClientClass.getConstructor(PendingIntent.class)
                        .newInstance(pendingIntent);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

public RemoteControlClientCompat(PendingIntent pendingIntent,Looper looper) {
    if (!sHasRemoteControlAPIs) {
        return;
    }

    try {
        mActualRemoteControlClient =
                sRemoteControlClientClass.getConstructor(PendingIntent.class,Looper.class)
                        .newInstance(pendingIntent,looper);
    } catch (Exception e) {
        Log.e(TAG,"Error creating new instance of " + sRemoteControlClientClass.getName(),e);
    }
}

/**
 * Class used to modify Metadata in a {@link android.media.RemoteControlClient} object. Use
 * {@link android.media.RemoteControlClient#editMetadata(boolean)} to create an instance of an
 * editor,on which you set the Metadata for the RemoteControlClient instance. Once all the
 * information has been set,use {@link #apply()} to make it the new Metadata that should be
 * displayed for the associated client. Once the Metadata has been "applied",you cannot reuse
 * this instance of the MetadataEditor.
 */
public class MetadataEditorCompat {

    private Method mputStringMethod;
    private Method mputBitmapMethod;
    private Method mputLongMethod;
    private Method mClearMethod;
    private Method mApplyMethod;

    private Object mActualMetadataEditor;

    /**
     * The Metadata key for the content artwork / album art.
     */
    public final static int MetaDATA_KEY_ARTWORK = 100;

    private MetadataEditorCompat(Object actualMetadataEditor) {
        if (sHasRemoteControlAPIs && actualMetadataEditor == null) {
            throw new IllegalArgumentException("Remote Control API's exist," +
                    "should not be given a null MetadataEditor");
        }
        if (sHasRemoteControlAPIs) {
            Class MetadataEditorClass = actualMetadataEditor.getClass();

            try {
                mputStringMethod = MetadataEditorClass.getmethod("putString",int.class,String.class);
                mputBitmapMethod = MetadataEditorClass.getmethod("putBitmap",Bitmap.class);
                mputLongMethod = MetadataEditorClass.getmethod("putLong",long.class);
                mClearMethod = MetadataEditorClass.getmethod("clear",new Class[]{});
                mApplyMethod = MetadataEditorClass.getmethod("apply",new Class[]{});
            } catch (Exception e) {
                throw new RuntimeException(e.getMessage(),e);
            }
        }
        mActualMetadataEditor = actualMetadataEditor;
    }

    /**
     * Adds textual information to be displayed.
     * Note that none of the information added after {@link #apply()} has been called,* will be displayed.
     * @param key The identifier of a the Metadata field to set. Valid values are
     *      {@link android.media.MediaMetadataRetriever#MetaDATA_KEY_ALBUM},*      {@link android.media.MediaMetadataRetriever#MetaDATA_KEY_albumartIST},*      {@link android.media.MediaMetadataRetriever#MetaDATA_KEY_TITLE},*      {@link android.media.MediaMetadataRetriever#MetaDATA_KEY_ARTIST},*      {@link android.media.MediaMetadataRetriever#MetaDATA_KEY_AUTHOR},*      {@link android.media.MediaMetadataRetriever#MetaDATA_KEY_COMPILATION},*      {@link android.media.MediaMetadataRetriever#MetaDATA_KEY_COMPOSER},*      {@link android.media.MediaMetadataRetriever#MetaDATA_KEY_DATE},*      {@link android.media.MediaMetadataRetriever#MetaDATA_KEY_GENRE},*      {@link android.media.MediaMetadataRetriever#MetaDATA_KEY_WRITER}.
     * @param value The text for the given key,or {@code null} to signify there is no valid
     *      information for the field.
     * @return Returns a reference to the same MetadataEditor object,so you can chain put
     *      calls together.
     */
    public MetadataEditorCompat putString(int key,String value) {
        if (sHasRemoteControlAPIs) {
            try {
                mputStringMethod.invoke(mActualMetadataEditor,key,value);
            } catch (Exception e) {
                throw new RuntimeException(e.getMessage(),e);
            }
        }
        return this;
    }

    /**
     * Sets the album / artwork picture to be displayed on the remote control.
     * @param key the identifier of the bitmap to set. The only valid value is
     *      {@link #MetaDATA_KEY_ARTWORK}
     * @param bitmap The bitmap for the artwork,or null if there isn't any.
     * @return Returns a reference to the same MetadataEditor object,so you can chain put
     *      calls together.
     * @throws IllegalArgumentException
     * @see android.graphics.Bitmap
     */
    public MetadataEditorCompat putBitmap(int key,Bitmap bitmap) {
        if (sHasRemoteControlAPIs) {
            try {
                mputBitmapMethod.invoke(mActualMetadataEditor,bitmap);
            } catch (Exception e) {
                throw new RuntimeException(e.getMessage(),e);
            }
        }
        return this;
    }

    /**
     * Adds numerical information to be displayed.
     * Note that none of the information added after {@link #apply()} has been called,* will be displayed.
     * @param key the identifier of a the Metadata field to set. Valid values are
     *      {@link android.media.MediaMetadataRetriever#MetaDATA_KEY_CD_TRACK_NUMBER},*      {@link android.media.MediaMetadataRetriever#MetaDATA_KEY_disC_NUMBER},*      {@link android.media.MediaMetadataRetriever#MetaDATA_KEY_DURATION} (with a value
     *      expressed in milliseconds),*      {@link android.media.MediaMetadataRetriever#MetaDATA_KEY_YEAR}.
     * @param value The long value for the given key
     * @return Returns a reference to the same MetadataEditor object,so you can chain put
     *      calls together.
     * @throws IllegalArgumentException
     */
    public MetadataEditorCompat putLong(int key,long value) {
        if (sHasRemoteControlAPIs) {
            try {
                mputLongMethod.invoke(mActualMetadataEditor,e);
            }
        }
        return this;
    }

    /**
     * Clears all the Metadata that has been set since the MetadataEditor instance was
     * created with {@link android.media.RemoteControlClient#editMetadata(boolean)}.
     */
    public void clear() {
        if (sHasRemoteControlAPIs) {
            try {
                mClearMethod.invoke(mActualMetadataEditor,(Object[]) null);
            } catch (Exception e) {
                throw new RuntimeException(e.getMessage(),e);
            }
        }
    }

    /**
     * Associates all the Metadata that has been set since the MetadataEditor instance was
     * created with {@link android.media.RemoteControlClient#editMetadata(boolean)},or since
     * {@link #clear()} was called,with the RemoteControlClient. Once "applied",this
     * MetadataEditor cannot be reused to edit the RemoteControlClient's Metadata.
     */
    public void apply() {
        if (sHasRemoteControlAPIs) {
            try {
                mApplyMethod.invoke(mActualMetadataEditor,e);
            }
        }
    }
}

/**
 * Creates a {@link android.media.RemoteControlClient.MetadataEditor}.
 * @param startEmpty Set to false if you want the MetadataEditor to contain the Metadata that
 *     was prevIoUsly applied to the RemoteControlClient,or true if it is to be created empty.
 * @return a new MetadataEditor instance.
 */
public MetadataEditorCompat editMetadata(boolean startEmpty) {
    Object MetadataEditor;
    if (sHasRemoteControlAPIs) {
        try {
            MetadataEditor = sRCCEditMetadataMethod.invoke(mActualRemoteControlClient,startEmpty);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    } else {
        MetadataEditor = null;
    }
    return new MetadataEditorCompat(MetadataEditor);
}

/**
 * Sets the current playback state.
 * @param state The current playback state,one of the following values:
 *       {@link android.media.RemoteControlClient#PLAYSTATE_STOPPED},*       {@link android.media.RemoteControlClient#PLAYSTATE_PAUSED},*       {@link android.media.RemoteControlClient#PLAYSTATE_PLAYING},*       {@link android.media.RemoteControlClient#PLAYSTATE_FAST_FORWARDING},*       {@link android.media.RemoteControlClient#PLAYSTATE_REWINDING},*       {@link android.media.RemoteControlClient#PLAYSTATE_SKIPPING_FORWARDS},*       {@link android.media.RemoteControlClient#PLAYSTATE_SKIPPING_BACKWARDS},*       {@link android.media.RemoteControlClient#PLAYSTATE_BUFFERING},*       {@link android.media.RemoteControlClient#PLAYSTATE_ERROR}.
 */
public void setPlaybackState(int state) {
    if (sHasRemoteControlAPIs) {
        try {
            sRCCSetPlayStateMethod.invoke(mActualRemoteControlClient,state);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

/**
 * Sets the flags for the media transport control buttons that this client supports.
 * @param transportControlFlags A combination of the following flags:
 *      {@link android.media.RemoteControlClient#FLAG_KEY_MEDIA_PREVIoUS},*      {@link android.media.RemoteControlClient#FLAG_KEY_MEDIA_REWIND},*      {@link android.media.RemoteControlClient#FLAG_KEY_MEDIA_PLAY},*      {@link android.media.RemoteControlClient#FLAG_KEY_MEDIA_PLAY_PAUSE},*      {@link android.media.RemoteControlClient#FLAG_KEY_MEDIA_PAUSE},*      {@link android.media.RemoteControlClient#FLAG_KEY_MEDIA_STOP},*      {@link android.media.RemoteControlClient#FLAG_KEY_MEDIA_FAST_FORWARD},*      {@link android.media.RemoteControlClient#FLAG_KEY_MEDIA_NEXT}
 */
public void setTransportControlFlags(int transportControlFlags) {
    if (sHasRemoteControlAPIs) {
        try {
            sRCCSetTransportControlFlags.invoke(mActualRemoteControlClient,transportControlFlags);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

public final Object getActualRemoteControlClientObject() {
    return mActualRemoteControlClient;
}
}

RemoteControlHelper类:

public class RemoteControlHelper {
private static final String TAG = "RemoteControlHelper";

private static boolean sHasRemoteControlAPIs = false;

private static Method sRegisterRemoteControlClientMethod;
private static Method sUnregisterRemoteControlClientMethod;

static {
    try {
        ClassLoader classLoader = RemoteControlHelper.class.getClassLoader();
        Class sRemoteControlClientClass =
                RemoteControlClientCompat.getActualRemoteControlClientClass(classLoader);
        sRegisterRemoteControlClientMethod = AudioManager.class.getmethod(
                "registerRemoteControlClient",new Class[]{sRemoteControlClientClass});
        sUnregisterRemoteControlClientMethod = AudioManager.class.getmethod(
                "unregisterRemoteControlClient",new Class[]{sRemoteControlClientClass});
        sHasRemoteControlAPIs = true;
    } catch (ClassNotFoundException e) {
        // Silently fail when running on an OS before ICS.
    } catch (NoSuchMethodException e) {
        // Silently fail when running on an OS before ICS.
    } catch (IllegalArgumentException e) {
        // Silently fail when running on an OS before ICS.
    } catch (SecurityException e) {
        // Silently fail when running on an OS before ICS.
    }
}

public static void registerRemoteControlClient(AudioManager audioManager,RemoteControlClientCompat remoteControlClient) {
    if (!sHasRemoteControlAPIs) {
        return;
    }

    try {
        sRegisterRemoteControlClientMethod.invoke(audioManager,remoteControlClient.getActualRemoteControlClientObject());
    } catch (Exception e) {
        Log.e(TAG,e.getMessage(),e);
    }
}


public static void unregisterRemoteControlClient(AudioManager audioManager,RemoteControlClientCompat remoteControlClient) {
    if (!sHasRemoteControlAPIs) {
        return;
    }

    try {
        sUnregisterRemoteControlClientMethod.invoke(audioManager,e);
    }
}
}

要更改lockPlayer状态dinamicaly:

 private void lockontrolsPlay() {
        if (mRemoteControlClientCompat != null) {
            mRemoteControlClientCompat
                    .setPlaybackState(RemoteControlClient.PLAYSTATE_PLAYING);
        }
    }

    private void lockontrolsPause() {
        if (mRemoteControlClientCompat != null) {
            mRemoteControlClientCompat
                    .setPlaybackState(RemoteControlClient.PLAYSTATE_PAUSED);
        }
    }

收件人:

public class MusicIntentReceiver extends WakefulbroadcastReceiver {
private int headsetSwitch = 1;


@Override
public void onReceive(Context context,Intent intent) {


    if (intent.getAction().equals(android.media.AudioManager.ACTION_AUdio_BECOMING_NOISY)) {


        Toast.makeText(context,MyApplication.getContext().getResources().getString (R.string.aptxt15),Toast.LENGTH_SHORT).show();
        intent = new Intent(context,ReproductorDialog.ServicioCanciones.class);
        intent.putExtra("do_action","pause_cascos");
        context.startService(intent);


    } else if (intent.getAction().equals(Intent.ACTION_MEDIA_BUTTON)) {

        KeyEvent keyEvent = (KeyEvent) intent.getExtras().get(Intent.EXTRA_KEY_EVENT);
        if (keyEvent.getAction() != KeyEvent.ACTION_DOWN)
            return;

        switch (keyEvent.getKeyCode()) {
            case KeyEvent.KEYCODE_HEADSETHOOK:


            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
                intent = new Intent(context,ReproductorDialog.ServicioCanciones.class);
                intent.putExtra("do_action","pause");
                context.startService(intent);
                //   context.startService(new Intent(MusicService.ACTION_TOGGLE_PLAYBACK));
                break;
            case KeyEvent.KEYCODE_MEDIA_PLAY:
                //  context.startService(new Intent(MusicService.ACTION_PLAY));
                intent = new Intent(context,"pause");
                context.startService(intent);
                break;
            case KeyEvent.KEYCODE_MEDIA_PAUSE:
                //  context.startService(new Intent(MusicService.ACTION_PAUSE));
                intent = new Intent(context,"pause");
                context.startService(intent);
                break;
            case KeyEvent.KEYCODE_MEDIA_STOP:
                //  context.startService(new Intent(MusicService.ACTION_STOP));
                break;
            case KeyEvent.KEYCODE_MEDIA_NEXT:
                intent = new Intent(context,"next");
                context.startService(intent);
                break;
            case KeyEvent.KEYCODE_MEDIA_PREVIoUS:
                // Todo: ensure that doing this in rapid succession actually plays the
                // prevIoUs song
                //   context.startService(new Intent(MusicService.ACTION_REWIND));
                intent = new Intent(context,"prevIoUs");
                context.startService(intent);
                break;
        }
    }
}
}

mAUdioManager是一个AudioManager对象,mMediaButtonReceiverComponent是一个ComponentName,简单地说就是

AudioManager mAudioManager; 
ComponentName mMediaButtonReceiverComponent;

调用方法lockScreenControls()之前.这些类在API 18上

原文地址:https://www.jb51.cc/android/431052.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐