当前位置:阳光沙滩 >Android > 查看文章
阿里云优惠码

1.获取到所有的表盘信息

关于表盘的获取,网上的资料也少,也只是怎么获取当前壁纸(表盘)。这里呢,就从思路上尝试去获取表盘。

思路:原理上来讲,表盘就是一个服务,动态壁纸,在后台不断地刷新。这样子的话,我们可以通过获取所有的服务,添加过滤即获取表盘。

1、拿到包管理器

2、通过包管理器去获取所有的服务,但是要添加过滤

3、还是看码吧,已经定了注释,相信聪明的你一定可以的

   private void getAllWallpapers() {


        //拿到包管理器
        final PackageManager mPackageManager = getPackageManager();

        //获取到包管理器(第二个参数过代表过滤形式,过滤形式有两种,一种是Intent,一种是Resolved)
        List<ResolveInfo> servicesLists = mPackageManager.queryIntentServices(new Intent(WallpaperService.SERVICE_INTERFACE),PackageManager.GET_META_DATA);

        //获取到集合的长度
        int size = servicesLists.size();

        //创建一个用来保存壁纸信息的集合
        mWallpaperInfos = new ArrayList<>(size);

        //看看获取到的和手表上的表盘数量是否一样
        Log.d(TAG, "size ==  " + size);

        //遍历服务数据
        for (int i = 0; i < size; i++) {

            //集合内容
            ResolveInfo resolveInfo = servicesLists.get(i);

            //使用组件信息来创建壁纸服务,当然,也可以先不new,用的时候再New,反正已经获取到了嘛。
            WallpaperInfo info;
            try {
                info = new WallpaperInfo(this, resolveInfo);
            } catch (XmlPullParserException e) {
                Log.w(TAG, "妈蛋,Xml解析错误... " + e.toString());
                continue;
            } catch (IOException e) {
                Log.w(TAG, "妈蛋,IO异常呢.... " +  e.toString());
                continue;
            }

            //此处应有掌声.....

            //把壁纸信息都添加到集合里头
            mWallpaperInfos.add(info);

        }
    }

 

2.更换表盘

普通的壁纸切换的方法是公开的,权限的public的。

这是通过设置Bitmap的形式来设置壁纸

  public void setBitmap(Bitmap bitmap) throws IOException {
            ....
}

这是通过设置流的形式来设置壁纸

 public void setStream(InputStream data) throws IOException {
        ......
}

这是设置资源文件的形式来设置壁纸

 public void setResource(@RawRes int resid) throws IOException {
      .....
}

貌似就是这几个了哈,具体请看WallpaperManager这个类。

那么设置动态壁纸呢,是私有的,并且是隐藏的,并并且是系统的api。在WallpaperManager类里可以找到如下代码:

/**
     * Set the live wallpaper.
     * 设置动态壁纸
     * This can only be called by packages with android.permission.SET_WALLPAPER_COMPONENT
     * permission.
     * 这只能被有更换权限的包(app)调用。
     * @hide(隐藏)
     */
    @SystemApi(系统api)
    public boolean setWallpaperComponent(ComponentName name) {
        if (sGlobals.mService == null) {
            Log.w(TAG, "WallpaperService not running");
            return false;
        }
        try {
            sGlobals.mService.setWallpaperComponentChecked(name, mContext.getOpPackageName());
            return true;
        } catch (RemoteException e) {
            // Ignore
        }
        return false;
    }

这个方法是隐藏的,我们可以通过反射方法去调用,参数嘛,前面我们已经准被好了表盘的信息,只有小手一抖就可以获取到ComponentName了。

ComponentName component = wallpaperInfo.getComponent();

 

重点来了:这个方法有Android Wear里有,也就是用模拟器的时候,可以获取到这个方法。但是,在百度的系统更里头,获取不到,会报NoSuchMethodException异常。

所以,我们在百度系统里就不能用这种方法了。可能它阉割掉了。反正实验结果就是:Android Wear原生系统可以获取到这个方法,而百度的系统上获取不到。

我们看看setWallpaperComponent这个方法它做了什么事呢?其实它呢,核心代码就一句:

sGlobals.mService.setWallpaperComponentChecked(name, mContext.getOpPackageName());

这里的mService是何方神圣呢?点进去看一看!

private IWallpaperManager mService;

 

原来这个mService是IwallpapaerManager,看到这里应该很熟悉了吧,是吧。这肯定是一个接口,它呢,用于连接修改表盘的服务。

更进一步来说,我们不通过上面这个方法来设置壁纸,直接使用接口里的方法来设置。接口的源码如下:

/** @hide */
interface IWallpaperManager {

 ......
    
    /**
     * Set the live wallpaper.
     */
    void setWallpaperComponent(in ComponentName name);
 
    ........
   
}

 

它还是hide的,同理通过反射就可以获取到了是吧,然后就可以设置动态壁纸啦!

这个在百度系统上可以哈,亲测可用!

/*这里通过反射,去获取到这个getIWallpaperManager()的方法,返回一个IWallpaperManager实例
  后面作为实例扔到invoke里头。
*/
receiver = (IWallpaperManager) mWallpaperManager
 .getClass()
 .getMethod("getIWallpaperManager", new Class[0])
 .invoke(mWallpaperManager, new Object[0]);

/*这里通过反射获取到setWallpaperComponent方法,来设置壁纸,实例对象就是这玩意啦*/
Class.forName("android.app.IWallpaperManager")
 .getMethod("setWallpaperComponent", new Class[]{ComponentName.class})
 .invoke(receiver, new Object[]{component});

 

好啦,到这里的话,你以为设置动态壁纸就搞定了,不是的哈,还有权限呢?

3.设置壁纸的权限

前面我们也看到了,修改动态壁纸是系统的API,也就是说这个需要系统的权限,在这个app的配置文件里添加了权限,还不行呢。还要对它进行系统签名,才真正有这样的权限去修改动态壁纸。

<uses-permission android:name="android.permission.SET_WALLPAPER_COMPONENT"/>

在配置文件里添加这个权限,我们可以看源码嘛,第一句话就是检查权限:

public void setWallpaperComponent(ComponentName name) {
       checkPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT);
       synchronized (mLock) {
          if (DEBUG) Slog.v(TAG, "setWallpaperComponent name=" + name);
           int userId = UserHandle.getCallingUserId();
           WallpaperData wallpaper = mWallpaperMap.get(userId);
          if (wallpaper == null) {
               throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
            }
           final long ident = Binder.clearCallingIdentity();
           try {
               wallpaper.imageWallpaperPending = false;
               bindWallpaperComponentLocked(name, false, true, wallpaper, null);
           } finally {
               Binder.restoreCallingIdentity(ident);
           }
       }
   }

有了权限之后,我们还需要进行系统签名,步骤如下:

1、生成APK,是APK就行了,有沒有签名都可以;

2、准备好这几个文件:

271111250535644i

其中,第一第二个是秘钥文件,这是系统的签名文件,这里的话,它是百度系统的签名。也就是说

用它签名后,就有权限在百度系统上的权限。但是,在Android Wear原生系统上是用不了哦!

然后,把APK复制到上面文件的文件夹里头,然后打开CMD,切换到上面文件夹下:

执行: java -jar signapk.jar platform..x509.pem plantform.pk8 应用名字.apk 签名后的名字.apk

好啦,到这里的话,就可以了。

 

7K
相关文章
为您推荐
各种观点