Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added "Fetch ResourceId/View in other plugins" #290

Merged
merged 7 commits into from
Aug 10, 2017
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@
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;
Expand Down Expand Up @@ -473,6 +476,76 @@ public static String fetchPluginNameByClassLoader(ClassLoader cl) {
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);
}

/**
* 获取所有插件的列表(指已安装的)
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,14 @@
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;
Expand All @@ -44,6 +46,8 @@

public class RePlugin {

static final String TAG = "RePlugin";

/**
* 表示目标进程根据实际情况自动调配
*/
Expand Down Expand Up @@ -512,6 +516,42 @@ public static String fetchPluginNameByClassLoader(ClassLoader cl) {
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);
}

/**
* 获取所有插件的列表(指已安装的)
*
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,12 @@
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;
Expand Down Expand Up @@ -277,15 +275,11 @@ public void onClick(View v) {
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();
Expand Down