package com.tencent.tws.pluginhost.plugindebug;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import tws.component.log.TwsLog;
import android.app.TwsActivity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Environment;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout.LayoutParams;
import android.widget.Toast;
import com.tencent.tws.pluginhost.R;
import com.tencent.tws.pluginhost.plugindebug.widget.StatusButton;
import com.tencent.tws.sharelib.SharePOJO;
import com.tws.plugin.bridge.TwsPluginBridgeActivity;
import com.tws.plugin.content.PluginDescriptor;
import com.tws.plugin.core.PluginLoader;
import com.tws.plugin.manager.InstallResult;
import com.tws.plugin.manager.PluginCallback;
import com.tws.plugin.manager.PluginManagerHelper;
import com.tws.plugin.util.FileUtil;
import com.tws.plugin.util.ResourceUtil;
public class DebugPluginActivity extends TwsActivity {
private static final String TAG = "rick_Print:MainActivity";
private ViewGroup mList;
private ViewGroup mBuiltinPlugList;
private ViewGroup mSdcardPluginList;
boolean isInstalled = false;
private HashMap<String, String> mBuildinMap = new HashMap<String, String>();
private String mInnerSDCardPath = "";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_debug_plugin);
setTitle("Host-插件调试界面");
// SD卡存放路径
mInnerSDCardPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/plugins";
File sdPlgusFile = new File(mInnerSDCardPath);
if (!sdPlgusFile.isDirectory() || !sdPlgusFile.exists()) {
sdPlgusFile.mkdirs();
}
initView();
// 监听插件安装 安装新插件后刷新当前页面
registerReceiver(pluginInstallEvent, new IntentFilter(PluginCallback.ACTION_PLUGIN_CHANGED));
}
private static final String ASSETS_PLUGS_DIR = "plugins";
private void initView() {
mList = (ViewGroup) findViewById(R.id.list);
mBuiltinPlugList = (ViewGroup) findViewById(R.id.builtin_plug_list);
mSdcardPluginList = (ViewGroup) findViewById(R.id.sdcard_plugin_list);
showInstalledAll();
showBuildinPluginList();
showSdcardPluginList();
}
private String mTmpFileName = "";
private void showSdcardPluginList() {
mSdcardPluginList.removeAllViews();
File file = new File(mInnerSDCardPath);
File[] subFile = file.listFiles();
if (subFile == null || subFile.length < 1) {
Toast.makeText(this, "Inner SDCard Plugins Path empty~!", Toast.LENGTH_SHORT).show();
findViewById(R.id.sdcard_plugin_text).setVisibility(View.GONE);
return;
} else {
findViewById(R.id.sdcard_plugin_text).setVisibility(View.VISIBLE);
}
for (File plugin : subFile) {
mTmpFileName = plugin.getName();
if (!mTmpFileName.endsWith(".apk"))
continue;
final StatusButton button = new StatusButton(this);
button.setPadding(15, 3, 3, 3);
LayoutParams layoutParam = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
layoutParam.topMargin = 3;
layoutParam.bottomMargin = 3;
layoutParam.gravity = Gravity.LEFT;
mSdcardPluginList.addView(button, layoutParam);
String fileNameWithoutFix = getApkFileName(mTmpFileName);
int iStatus = StatusButton.UNINSTALL_PLUGIN;
if (mBuildinMap.containsKey(fileNameWithoutFix)) {
iStatus = StatusButton.INSTALLED_PLUGIN;
}
button.setStatus(iStatus);
// pluginFile位插件的文件全名,便于点击获取插件的文件名
button.setPluginLabel(mTmpFileName);
// 登录和配对的属于DM依赖插件暂时不让卸载
if (mTmpFileName.startsWith("TwsPluginLogin") || mTmpFileName.startsWith("TwsPluginPair")) {
if (iStatus == StatusButton.INSTALLED_PLUGIN) {
button.setEnabled(false);
}
}
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (view instanceof StatusButton) {
final StatusButton buttonEx = (StatusButton) view;
if (buttonEx.getStatus() == StatusButton.INSTALLED_PLUGIN) {
String pluginLabel = (String) buttonEx.getPluginLabel();
String pluginId = mBuildinMap.get(getApkFileName(pluginLabel));
if (!TextUtils.isEmpty(pluginId)) {
PluginManagerHelper.remove(pluginId);
buttonEx.setStatus(StatusButton.UNINSTALL_PLUGIN);
}
} else {
String apkName = (String) buttonEx.getPluginLabel();
PluginManagerHelper.installPlugin(mInnerSDCardPath + "//" + apkName);
buttonEx.setStatus(StatusButton.INSTALLED_PLUGIN);
}
}
}
});
}
}
private void showBuildinPluginList() {
mBuiltinPlugList.removeAllViews();
String[] mBuildInPlugins = null;
try {
mBuildInPlugins = getAssets().list(ASSETS_PLUGS_DIR);
} catch (IOException e) {
e.printStackTrace();
}
for (String pluginFile : mBuildInPlugins) {
if (!pluginFile.endsWith(".apk"))
continue;
final StatusButton button = new StatusButton(this);
button.setPadding(15, 3, 3, 3);
LayoutParams layoutParam = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
layoutParam.topMargin = 3;
layoutParam.bottomMargin = 3;
layoutParam.gravity = Gravity.LEFT;
mBuiltinPlugList.addView(button, layoutParam);
String fileNameWithoutFix = getApkFileName(pluginFile);
int iStatus = StatusButton.UNINSTALL_PLUGIN;
if (mBuildinMap.containsKey(fileNameWithoutFix)) {
iStatus = StatusButton.INSTALLED_PLUGIN;
}
button.setStatus(iStatus);
// pluginFile位插件的文件全名,便于点击获取插件的文件名
button.setPluginLabel(pluginFile);
// 登录和配对的属于DM依赖插件暂时不让卸载
if (pluginFile.startsWith("TwsPluginLogin") || pluginFile.startsWith("TwsPluginPair")) {
if (iStatus == StatusButton.INSTALLED_PLUGIN) {
button.setEnabled(false);
}
}
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
TwsLog.d(TAG, "onClick:" + view);
if (view instanceof StatusButton) {
final StatusButton buttonEx = (StatusButton) view;
if (buttonEx.getStatus() == StatusButton.INSTALLED_PLUGIN) {
String pluginLabel = (String) buttonEx.getPluginLabel();
String pluginId = mBuildinMap.get(getApkFileName(pluginLabel));
if (!TextUtils.isEmpty(pluginId)) {
PluginManagerHelper.remove(pluginId);
buttonEx.setStatus(StatusButton.UNINSTALL_PLUGIN);
}
} else {
PluginLoader.copyAndInstall(ASSETS_PLUGS_DIR + "/" + (String) buttonEx.getPluginLabel());
buttonEx.setStatus(StatusButton.INSTALLED_PLUGIN);
}
}
}
});
}
}
private String getApkFileName(String apkFile) {
if (!apkFile.endsWith(".apk"))
return null;
return apkFile.substring(0, apkFile.length() - 4);
}
private void showInstalledAll() {
mBuildinMap.clear();
ViewGroup root = mList;
root.removeAllViews();
// 列出所有已经安装的插件
Collection<PluginDescriptor> plugins = PluginManagerHelper.getPlugins();
Iterator<PluginDescriptor> itr = plugins.iterator();
while (itr.hasNext()) {
final PluginDescriptor pluginDescriptor = itr.next();
Button button = new Button(this);
button.setPadding(9, 0, 9, 0);
LayoutParams layoutParam = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
layoutParam.topMargin = 3;
layoutParam.bottomMargin = 3;
layoutParam.gravity = Gravity.LEFT;
root.addView(button, layoutParam);
TwsLog.d(TAG, "插件id:" + pluginDescriptor.getPackageName());
String pluginLabel = ResourceUtil.getLabel(pluginDescriptor);
mBuildinMap.put(pluginLabel, pluginDescriptor.getPackageName());
button.setText("打开插件:" + pluginLabel + ", V" + pluginDescriptor.getVersion());
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent launchIntent = getPackageManager().getLaunchIntentForPackage(
pluginDescriptor.getPackageName());
if (launchIntent == null) {
Toast.makeText(DebugPluginActivity.this,
"插件" + pluginDescriptor.getPackageName() + "没有配置Launcher", Toast.LENGTH_SHORT).show();
// 没有找到Launcher,打开插件详情
Intent intent = new Intent(DebugPluginActivity.this, PluginDetailActivity.class);
intent.putExtra("plugin_id", pluginDescriptor.getPackageName());
startActivity(intent);
} else {
// 打开插件的Launcher界面
if (!pluginDescriptor.isStandalone()) {
// 测试向非独立插件传宿主中定义的VO对象
launchIntent.putExtra("paramVO", new SharePOJO("宿主传过来的测试VO"));
}
startActivity(launchIntent);
}
}
});
}
Button button = new Button(this);
button.setPadding(9, 0, 9, 0);
LayoutParams layoutParam = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
layoutParam.topMargin = 3;
layoutParam.bottomMargin = 3;
layoutParam.gravity = Gravity.LEFT;
root.addView(button, layoutParam);
button.setText("手动打开BridgeActivity");
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(DebugPluginActivity.this, TwsPluginBridgeActivity.class);
startActivity(intent);
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(pluginInstallEvent);
if (scn != null) {
unbindService(scn);
scn = null;
}
};
private ServiceConnection scn;
private final BroadcastReceiver pluginInstallEvent = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
int actionType = intent.getIntExtra(PluginCallback.EXTRA_TYPE, PluginCallback.TYPE_UNKNOW);
int code = intent.getIntExtra(PluginCallback.EXTRA_RESULT_CODE, -1);
String packageName = intent.getStringExtra(PluginCallback.EXTRA_ID);
String des = getActionDes(actionType)
+ (actionType == PluginCallback.TYPE_REMOVE_ALL ? "" : (" 插件:" + packageName)) + " "
+ getErrMsg(code);
Toast.makeText(DebugPluginActivity.this, des, Toast.LENGTH_SHORT).show();
TwsLog.d(TAG, "");
showInstalledAll();
showBuildinPluginList();
showSdcardPluginList();
};
};
private static String getActionDes(int actionType) {
switch (actionType) {
case PluginCallback.TYPE_INSTALL:
return "安装";
case PluginCallback.TYPE_REMOVE:
return "卸载";
case PluginCallback.TYPE_REMOVE_ALL:
return "卸载所有";
case PluginCallback.TYPE_START:
return "启动";
case PluginCallback.TYPE_STOP:
return "停止";
default:
return "未知操作";
}
}
private static String getErrMsg(int code) {
String msg = "";
switch (code) {
case InstallResult.SUCCESS:
msg = "成功";
break;
case InstallResult.SRC_FILE_NOT_FOUND:
msg = "失败: 安装文件未找到";
break;
case InstallResult.COPY_FILE_FAIL:
msg = "失败: 复制安装文件到安装目录失败";
break;
case InstallResult.SIGNATURES_INVALIDATE:
msg = "失败: 安装文件验证失败";
break;
case InstallResult.VERIFY_SIGNATURES_FAIL:
msg = "失败: 插件和宿主签名串不匹配";
break;
case InstallResult.PARSE_MANIFEST_FAIL:
msg = "失败: 插件Manifest文件解析出错";
break;
case InstallResult.FAIL_BECAUSE_HAS_LOADED:
msg = "失败: 同版本插件已加载,无需安装";
break;
case InstallResult.MIN_API_NOT_SUPPORTED:
msg = "失败: 当前系统版本过低,不支持此插件";
break;
default:
msg = "失败: 其他 code=" + code;
}
return msg;
}
@Override
protected void onResume() {
super.onResume();
// 打印一下目录结构
FileUtil.printAll(new File(getApplicationInfo().dataDir));
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
TwsLog.d(TAG, "onKeyDown keyCode=" + keyCode);
return super.onKeyDown(keyCode, event);
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
TwsLog.d(TAG, "onKeyUp keyCode=" + keyCode);
return super.onKeyUp(keyCode, event);
}
}