Merge pull request #290 from jiongxuan/feature_get_resource

Added "Fetch ResourceId/View in other plugins"
This commit is contained in:
cundong 2017-08-10 18:51:51 +08:00 committed by GitHub
commit 766bdf741e
4 changed files with 215 additions and 10 deletions

View File

@ -32,6 +32,9 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.support.v4.content.LocalBroadcastManager;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.qihoo360.i.Factory;
import com.qihoo360.i.Factory2;
@ -473,6 +476,76 @@ public class RePlugin {
return Factory.fetchPluginName(cl);
}
/**
* 通过资源名包括前缀和具体名字来获取指定插件里的资源的ID
* <p>
* 性能消耗等同于 fetchResources
*
* @param pluginName 插件名
* @param resTypeAndName 要获取的资源类型+资源名格式为[type]/[name]例如 <p>
* layout/common_title 布局里获取common_title的ID <p>
* drawable/common_bg 可绘制图片里获取common_bg的ID <p>
* 详细见Android官方的说明
* @return 资源的ID若为0则表示资源没有找到无法使用
* @since 2.2.0
*/
public static int fetchResourceIdByName(String pluginName, String resTypeAndName) {
PackageInfo pi = fetchPackageInfo(pluginName);
if (pi == null) {
// 插件没有找到
if (LogDebug.LOG) {
LogDebug.e(TAG, "fetchResourceIdByName: Plugin not found. pn=" + pluginName + "; resName=" + resTypeAndName);
}
return 0;
}
Resources res = fetchResources(pluginName);
if (res == null) {
// 不太可能出现此问题同样为插件没有找到
if (LogDebug.LOG) {
LogDebug.e(TAG, "fetchResourceIdByName: Plugin not found (fetchResources). pn=" + pluginName + "; resName=" + resTypeAndName);
}
return 0;
}
// Identifier的第一个参数想要的是
// [包名]:[类型名]/[资源名]其中[类型名]/[资源名]就是 resTypeAndName 参数
// 例如com.qihoo360.replugin.sample.demo2:layout/from_demo1
String idKey = pi.packageName + ":" + resTypeAndName;
return res.getIdentifier(idKey, null, null);
}
/**
* 通过Layout名来获取插件内的View
*
* @param pluginName 插件名
* @param layoutName Layout名字
* @param root Optional view to be the parent of the generated hierarchy.
* @return 插件的View若为Null则表示获取失败
* @since 2.2.0
*/
public static View fetchViewByLayoutName(String pluginName, String layoutName, ViewGroup root) {
Context context = fetchContext(pluginName);
if (context == null) {
// 插件没有找到
if (LogDebug.LOG) {
LogDebug.e(TAG, "fetchViewByLayoutName: Plugin not found. pn=" + pluginName + "; layoutName=" + layoutName);
}
}
String resTypeAndName = "layout/" + layoutName;
int id = fetchResourceIdByName(pluginName, resTypeAndName);
if (id <= 0) {
// 无法拿到资源可能是资源没有找到
if (LogDebug.LOG) {
LogDebug.e(TAG, "fetchViewByLayoutName: fetch failed! pn=" + pluginName + "; layoutName=" + layoutName);
}
return null;
}
// TODO 可能要考虑WebView在API 19以上的特殊性
return LayoutInflater.from(context).inflate(id, root);
}
/**
* 获取所有插件的列表指已安装的
*

View File

@ -25,12 +25,14 @@ import android.content.res.Resources;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
import android.view.View;
import android.view.ViewGroup;
import com.qihoo360.replugin.i.IPluginManager;
import com.qihoo360.replugin.utils.ParcelUtils;
import com.qihoo360.replugin.helper.LogDebug;
import com.qihoo360.replugin.i.IPluginManager;
import com.qihoo360.replugin.model.PluginInfo;
import com.qihoo360.replugin.packages.PluginRunningList;
import com.qihoo360.replugin.utils.ParcelUtils;
import java.util.ArrayList;
import java.util.List;
@ -44,6 +46,8 @@ import java.util.List;
public class RePlugin {
static final String TAG = "RePlugin";
/**
* 表示目标进程根据实际情况自动调配
*/
@ -512,6 +516,42 @@ public class RePlugin {
return null;
}
/**
* 通过资源名包括前缀和具体名字来获取指定插件里的资源的ID
* <p>
* 性能消耗等同于 fetchResources
*
* @param pluginName 插件名
* @param resTypeAndName 要获取的资源类型+资源名格式为[type]/[name]例如 <p>
* layout/common_title 布局里获取common_title的ID <p>
* drawable/common_bg 可绘制图片里获取common_bg的ID <p>
* 详细见Android官方的说明
* @return 资源的ID若为0则表示资源没有找到无法使用
* @since 2.2.0 (老的host-lib版本也能使用)
*/
public static int fetchResourceIdByName(String pluginName, String resTypeAndName) {
if (!RePluginFramework.mHostInitialized) {
return 0;
}
return RePluginCompat.fetchResourceIdByName(pluginName, resTypeAndName);
}
/**
* 通过Layout名来获取插件内的View
*
* @param pluginName 插件名
* @param layoutName Layout名字
* @param root Optional view to be the parent of the generated hierarchy.
* @return 插件的View若为Null则表示获取失败
* @since 2.2.0 (老的host-lib版本也能使用)
*/
public static View fetchViewByLayoutName(String pluginName, String layoutName, ViewGroup root) {
if (!RePluginFramework.mHostInitialized) {
return null;
}
return RePluginCompat.fetchViewByLayoutName(pluginName, layoutName, root);
}
/**
* 获取所有插件的列表指已安装的
*

View File

@ -0,0 +1,98 @@
/*
* Copyright (C) 2005-2017 Qihoo 360 Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed To in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.qihoo360.replugin;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.res.Resources;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.qihoo360.replugin.helper.LogDebug;
import static com.qihoo360.replugin.RePlugin.TAG;
import static com.qihoo360.replugin.RePlugin.fetchContext;
import static com.qihoo360.replugin.RePlugin.fetchPackageInfo;
import static com.qihoo360.replugin.RePlugin.fetchResources;
/**
* 为了兼容旧版本RePlugin而做的类 <p>
* 必须和host-lib中的方法近乎完全一样才可以避免出现行为不一致的问题 <p>
* <p>
* 注意依赖host-lib内部调用的例如调用了Loader的逻辑等或者行为高度和宿主一致的则还是应该走正常的反射流程
*
* @author RePlugin Team
* @since 2.2.0
*/
class RePluginCompat {
/**
* @see RePlugin#fetchResourceIdByName(String, String)
*/
static int fetchResourceIdByName(String pluginName, String resTypeAndName) {
PackageInfo pi = fetchPackageInfo(pluginName);
if (pi == null) {
// 插件没有找到
if (LogDebug.LOG) {
LogDebug.e(TAG, "fetchResourceIdByName: Plugin not found. pn=" + pluginName + "; resName=" + resTypeAndName);
}
return 0;
}
Resources res = fetchResources(pluginName);
if (res == null) {
// 不太可能出现此问题同样为插件没有找到
if (LogDebug.LOG) {
LogDebug.e(TAG, "fetchResourceIdByName: Plugin not found (fetchResources). pn=" + pluginName + "; resName=" + resTypeAndName);
}
return 0;
}
// Identifier的第一个参数想要的是
// [包名]:[类型名]/[资源名]其中[类型名]/[资源名]就是 resTypeAndName 参数
// 例如com.qihoo360.replugin.sample.demo2:layout/from_demo1
String idKey = pi.packageName + ":" + resTypeAndName;
return res.getIdentifier(idKey, null, null);
}
/**
* @see RePlugin#fetchViewByLayoutName(String, String, ViewGroup)
*/
static View fetchViewByLayoutName(String pluginName, String layoutName, ViewGroup root) {
Context context = fetchContext(pluginName);
if (context == null) {
// 插件没有找到
if (LogDebug.LOG) {
LogDebug.e(TAG, "fetchViewByLayoutName: Plugin not found. pn=" + pluginName + "; layoutName=" + layoutName);
}
}
String resTypeAndName = "layout/" + layoutName;
int id = fetchResourceIdByName(pluginName, resTypeAndName);
if (id <= 0) {
// 无法拿到资源可能是资源没有找到
if (LogDebug.LOG) {
LogDebug.e(TAG, "fetchViewByLayoutName: fetch failed! pn=" + pluginName + "; layoutName=" + layoutName);
}
return null;
}
// TODO 可能要考虑WebView在API 19以上的特殊性
return LayoutInflater.from(context).inflate(id, root);
}
}

View File

@ -22,14 +22,12 @@ import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
@ -277,15 +275,11 @@ public class MainActivity extends Activity {
mItems.add(new TestItem("Resources: Use demo2's layout", new View.OnClickListener() {
@Override
public void onClick(View v) {
Resources res = RePlugin.fetchResources("demo2");
int id = res.getIdentifier("com.qihoo360.replugin.sample.demo2:layout/from_demo1", null, null);
if (id == 0) {
View contentView = RePlugin.fetchViewByLayoutName("demo2", "from_demo1", null);
if (contentView == null) {
Toast.makeText(v.getContext(), "from_demo1 Not Found", Toast.LENGTH_SHORT).show();
return;
}
// 这块儿得拿demo2的Context才能Inflate到资源
View contentView = LayoutInflater.from(RePlugin.fetchContext("demo2")).inflate(id, null);
Dialog d = new Dialog(v.getContext());
d.setContentView(contentView);
d.show();