当前位置: 首页 > news >正文

网站建设 岗位做男装比较好的网站有哪些

网站建设 岗位,做男装比较好的网站有哪些,枣庄住房和城乡建设局网站,h5是啥背景 在研究sdk插件化热更新方式的过程中总结出了两套插件资源加载方案#xff0c;在此记录下 资源热更方式 方式一#xff1a;合并所有插件资源 需要解决资源id冲突问题 资源ID值一共4个字段#xff0c;由三部分组成#xff1a;PackageIdTypeIdEntryId PackageId在此记录下 资源热更方式 方式一合并所有插件资源 需要解决资源id冲突问题 资源ID值一共4个字段由三部分组成PackageIdTypeIdEntryId PackageId是包的Id值Android 中如果第三方应用的话这个默认值是 0x7f系统应用的话就是 0x01 插件的话那么就是给插件分配的id值占用1个字节。TypeId是资源的类型Id值一般 Android 中有这几个类型attrdrawablelayoutanimrawdimenstringboolstyleintegerarraycoloridmenu 等。【应用程序所有模块中的资源类型名称按照字母排序之后。值是从1开支逐渐递增的而且顺序不能改变每个模块下的R文件的相同资源类型id值相同)。比如anim0x01占用1个字节那么在这个编译出的所有R文件中anim 的值都是 0x01】EntryId:是在具体的类型下资源实例的id值从0开始依次递增他占用2个字节。 两种解决方式 gradle3.5以上可以动态配置aapt的package-id参数修改插件apk的packageId可在插件模块的build.gradle配置如下 android {compileSdkVersion 32defaultConfig {applicationId xxxminSdkVersion 21targetSdkVersion 32versionCode 1versionName 1.0}buildTypes {release {minifyEnabled falseproguardFiles getDefaultProguardFile(proguard-android.txt), proguard-rules.pro}}compileOptions {sourceCompatibility JavaVersion.VERSION_1_8targetCompatibility JavaVersion.VERSION_1_8}//为模块定一个唯一的package-id如0x80aaptOptions {additionalParameters --allow-reserved-package-id,--package-id, 0x80} }gradle3.5以下可以将打包出来的插件apk包进行解包修改public.xml文件内资源id的package-id再扫描每一个R$xxx.smali文件纠正代码中R类的值与public.xml中的对应重新打包。 反射替换Application中的mResources字段 注意在启动service和receiver的时候会使用application的resource fun mergePatchResources(application: Application, apkPaths : ListString) {val newAssetManagerObj AssetManager::class.java.newInstance()//todo 需要注意这里的addAssetPath被标志为废弃了val addAssetPath AssetManager::class.java.getMethod(addAssetPath, String::class.java)// 插入宿主的资源addAssetPath.invoke(newAssetManagerObj, application.baseContext.packageResourcePath)// 插入插件的资源apkPaths.forEach {addAssetPath.invoke(newAssetManagerObj, it)}val newResourcesObj Resources(newAssetManagerObj,application.baseContext.resources.displayMetrics,application.baseContext.resources.configuration)newHoldResources newResourcesObjval resourcesField application.baseContext.javaClass.getDeclaredField(mResources)resourcesField.isAccessible trueresourcesField[application.baseContext] newResourcesObjval packageInfoField application.baseContext.javaClass.getDeclaredField(mPackageInfo)packageInfoField.isAccessible trueval packageInfoObj packageInfoField[application.baseContext]// 获取 mPackageInfo 变量对象中类的Resources类型的mResources 变量并替换它的值为新的Resources对象// 注意这是最主要的需要替换的如果不需要支持插件运行时更新只留这一个就可以了val resourcesField2 packageInfoObj.javaClass.getDeclaredField(mResources)resourcesField2.isAccessible trueresourcesField2[packageInfoObj] newResourcesObj// 获取 ContextImpl 中的 Resources.Theme 类型的 mTheme 变量并至空它// 注意清理mTheme对象否则通过inflate方式加载资源会报错, 如果是activity动态加载插件则需要把activity的mTheme对象也设置为nullval themeField application.baseContext.javaClass.getDeclaredField(mTheme)themeField.isAccessible truethemeField[application.baseContext] null }更新Activity的资源 监听activity的onCreate回调 ((Application)context).registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {Overridepublic void onActivityCreated(NonNull Activity activity, Nullable Bundle savedInstanceState) {Log.d(zbm111, doMonitorActivity---onCreate);Resources resources 含宿主和所有插件资源的完整resource对象ResHookUtil.monkeyPatchExistingResources(activity, resources);}Overridepublic void onActivityStarted(NonNull Activity activity) {}Overridepublic void onActivityResumed(NonNull Activity activity) {}Overridepublic void onActivityPaused(NonNull Activity activity) {}Overridepublic void onActivityStopped(NonNull Activity activity) {}Overridepublic void onActivitySaveInstanceState(NonNull Activity activity, NonNull Bundle outState) {}Overridepublic void onActivityDestroyed(NonNull Activity activity) {}});将要启动的activity反射替换mResources字段 public static void monkeyPatchExistingResources(Activity activity, Resources newResources) {try {Class? contextThemeWrapperClass null;try {contextThemeWrapperClass Class.forName(android.view.ContextThemeWrapper);} catch (ClassNotFoundException e) {e.printStackTrace();}// 反射获取 ContextThemeWrapper 类的 mResources 字段Field mResourcesField null;try {mResourcesField contextThemeWrapperClass.getDeclaredField(mResources);} catch (NoSuchFieldException e) {e.printStackTrace();}// 设置字段可见性mResourcesField.setAccessible(true);// 将插件资源设置到插件 Activity 中try {mResourcesField.set(activity, newResources);} catch (IllegalAccessException e) {e.printStackTrace();}Method mTheme contextThemeWrapperClass.getDeclaredMethod(setTheme, Resources.Theme.class);mTheme.setAccessible(true);mTheme.invoke(activity, (Object) null);} catch (Exception e) {e.printStackTrace();}}方式二封装含插件资源的Resource对象 注意插件apk的包名须与宿主的包名保持一致 需要解决资源id冲突问题 参考方式一可以通过修改type id与宿主区分开 hook ActivityThread的handler设置callback 给ActivityThread中mHHander类型对象的mCallback字段设置一个代理对象ProxyHandlerCallback public static void doHandlerHook(Context context) {try {HookUtils.context context;Class? activityThreadClass Class.forName(android.app.ActivityThread);Method currentActivityThread activityThreadClass.getDeclaredMethod(currentActivityThread);Object activityThread currentActivityThread.invoke(null);Field mHField activityThreadClass.getDeclaredField(mH);mHField.setAccessible(true);Handler mH (Handler) mHField.get(activityThread);Field mCallbackField Handler.class.getDeclaredField(mCallback);mCallbackField.setAccessible(true);mCallbackField.set(mH, new ProxyHandlerCallback(mH));} catch (Exception e) {e.printStackTrace();}}系统启动service前进行拦截将ActivityThread的mPackages新增一个service的LoadedApk该LoadedApk的mResources字段替换为含插件宿主资源的SingleMixRes对象 系统启动receiver前进行拦截将application的mResources字段替换为含插件宿主资源的SingleMixRes对象。 public class ProxyHandlerCallback implements Handler.Callback {private Handler mBaseHandler;private MapString, String mPathToPluginNameMap new HashMap();public ProxyHandlerCallback(Handler mBaseHandler) {this.mBaseHandler mBaseHandler;}Overridepublic boolean handleMessage(Message msg) {Log.d(zbm111, 接受到消息了msg: msg);if (msg.what 113){//启动receiver的时候走这里try {Object object msg.obj;Field infoField object.getClass().getDeclaredField(info);infoField.setAccessible(true);ActivityInfo activityInfo (ActivityInfo) infoField.get(object);String hostReceiverName activityInfo.name;Resources resources 含插件宿主资源的SingleMixRes对象;Field resourcesField ((Application)HookUtils.getContext()).getBaseContext().getClass().getDeclaredField(mResources);resourcesField.setAccessible(true);resourcesField.set(((Application)HookUtils.getContext()).getBaseContext(), resources);}catch (Exception e){Log.e(zbm111, handle create receiver failed);}} else if (msg.what 114) {//启动service的时候走这里try {Object object msg.obj;Field infoField object.getClass().getDeclaredField(info);infoField.setAccessible(true);ServiceInfo serviceInfo (ServiceInfo) infoField.get(object);String hostServiceName serviceInfo.name;String path 插件apk本地存储路径//todo dex热修复必须同时进行资源热更if (path ! null) {replaceLoadApk(hostServiceName, path, false);Log.i(zbm111, replaced to plugin service success);}} catch (Exception e) {Log.e(zbm111, handle create service failed);}}mBaseHandler.handleMessage(msg);return true;}private void replaceLoadApk(String componentName, String path, boolean isUseActivity) throws Exception {Log.i(zbm111, start replaceLoadApk);Field activityThreadField Class.forName(android.app.ActivityThread).getDeclaredField(sCurrentActivityThread);activityThreadField.setAccessible(true);Object sCurrentActivityThread activityThreadField.get(null);Field mPackagesField sCurrentActivityThread.getClass().getDeclaredField(mPackages);mPackagesField.setAccessible(true);ArrayMap mPackages (ArrayMap) mPackagesField.get(sCurrentActivityThread);if (null mPackages) {Log.i(zbm111, can not get mPackages);return;}ApplicationInfo applicationInfo generateApplicationInfo(path);if (null ! applicationInfo) {Field compatibilityInfoField Class.forName(android.content.res.CompatibilityInfo).getDeclaredField(DEFAULT_COMPATIBILITY_INFO);compatibilityInfoField.setAccessible(true);Object defaultCompatibilityInfo compatibilityInfoField.get(null);Object loadedApk;if (isUseActivity){Method getPackageInfoMethod sCurrentActivityThread.getClass().getDeclaredMethod(getPackageInfo, ApplicationInfo.class, Class.forName(android.content.res.CompatibilityInfo), int.class);getPackageInfoMethod.setAccessible(true);loadedApk getPackageInfoMethod.invoke(sCurrentActivityThread, applicationInfo, defaultCompatibilityInfo, Context.CONTEXT_INCLUDE_CODE);}else {Method getPackageInfoMethod sCurrentActivityThread.getClass().getDeclaredMethod(getPackageInfoNoCheck, ApplicationInfo.class, Class.forName(android.content.res.CompatibilityInfo));getPackageInfoMethod.setAccessible(true);loadedApk getPackageInfoMethod.invoke(sCurrentActivityThread, applicationInfo, defaultCompatibilityInfo);}String pluginName applicationInfo.packageName;if (!TextUtils.isEmpty(pluginName)) {Log.i(zbm111, plugin pkg name is pluginName);Resources resources 含插件宿主资源的SingleMixRes对象;setResource(loadedApk, resources);mPackages.put(pluginName, new WeakReference(loadedApk));mPackagesField.set(sCurrentActivityThread, mPackages);mPathToPluginNameMap.put(path, pluginName);} else {Log.i(zbm111, get plugin pkg name failed);}} else {Log.i(zbm111, can not get application info);}}private void setResource(Object loadedApk, Resources resources) throws Exception{Field mResourcesField loadedApk.getClass().getDeclaredField(mResources);mResourcesField.setAccessible(true);mResourcesField.set(loadedApk, resources);}public ApplicationInfo generateApplicationInfo(String pluginPath) {try {ApplicationInfo applicationInfo getApplicationInfoByPackageArchiveInfo(pluginPath);if (null applicationInfo) {LogUtil.i(zbm111, get applicationInfo failed);return null;}applicationInfo.sourceDir pluginPath;applicationInfo.publicSourceDir pluginPath;return applicationInfo;} catch (Exception e) {LogUtil.i(zbm111, generateApplicationzInfo failed e.getMessage());}return null;}private ApplicationInfo getApplicationInfoByPackageArchiveInfo(String pluginPath) {PackageManager packageManager HookUtils.getContext().getPackageManager();if (null packageManager) {LogUtil.i(zbm111, get PackageManager failed);return null;}PackageInfo packageInfo packageManager.getPackageArchiveInfo(pluginPath, 0);if (null packageInfo) {LogUtil.i(zbm111, get packageInfo failed);return null;}return packageInfo.applicationInfo;} }自定义ResourcesWrapper public class ResourcesWrapper extends Resources {private Resources mBase;public ResourcesWrapper(Resources base){super(base.getAssets(),base.getDisplayMetrics(),base.getConfiguration());mBase base;}Overridepublic CharSequence getText(int id) throws NotFoundException {return mBase.getText(id);}TargetApi(Build.VERSION_CODES.O)Overridepublic Typeface getFont(int id) throws NotFoundException {return mBase.getFont(id);}Overridepublic CharSequence getQuantityText(int id, int quantity) throws NotFoundException {return mBase.getQuantityText(id, quantity);}Overridepublic String getString(int id) throws NotFoundException {return mBase.getString(id);}Overridepublic String getString(int id, Object... formatArgs) throws NotFoundException {return mBase.getString(id, formatArgs);}Overridepublic String getQuantityString(int id, int quantity, Object... formatArgs) throws NotFoundException {return mBase.getQuantityString(id, quantity, formatArgs);}Overridepublic String getQuantityString(int id, int quantity) throws NotFoundException {return mBase.getQuantityString(id, quantity);}Overridepublic CharSequence getText(int id, CharSequence def) {return mBase.getText(id, def);}Overridepublic CharSequence[] getTextArray(int id) throws NotFoundException {return mBase.getTextArray(id);}Overridepublic String[] getStringArray(int id) throws NotFoundException {return mBase.getStringArray(id);}Overridepublic int[] getIntArray(int id) throws NotFoundException {return mBase.getIntArray(id);}Overridepublic TypedArray obtainTypedArray(int id) throws NotFoundException {return mBase.obtainTypedArray(id);}Overridepublic float getDimension(int id) throws NotFoundException {return mBase.getDimension(id);}Overridepublic int getDimensionPixelOffset(int id) throws NotFoundException {return mBase.getDimensionPixelOffset(id);}Overridepublic int getDimensionPixelSize(int id) throws NotFoundException {return mBase.getDimensionPixelSize(id);}Overridepublic float getFraction(int id, int base, int pbase) {return mBase.getFraction(id, base, pbase);}Overridepublic Drawable getDrawable(int id) throws NotFoundException {return mBase.getDrawable(id);}TargetApi(Build.VERSION_CODES.LOLLIPOP)Overridepublic Drawable getDrawable(int id, Theme theme) throws NotFoundException {return mBase.getDrawable(id, theme);}Overridepublic Drawable getDrawableForDensity(int id, int density) throws NotFoundException {if (Build.VERSION.SDK_INT Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {return mBase.getDrawableForDensity(id, density);} else {return null;}}TargetApi(Build.VERSION_CODES.LOLLIPOP)Overridepublic Drawable getDrawableForDensity(int id, int density, Theme theme) {return mBase.getDrawableForDensity(id, density, theme);}Overridepublic Movie getMovie(int id) throws NotFoundException {return mBase.getMovie(id);}Overridepublic int getColor(int id) throws NotFoundException {return mBase.getColor(id);}TargetApi(Build.VERSION_CODES.M)Overridepublic int getColor(int id, Theme theme) throws NotFoundException {return mBase.getColor(id, theme);}Overridepublic ColorStateList getColorStateList(int id) throws NotFoundException {return mBase.getColorStateList(id);}TargetApi(Build.VERSION_CODES.M)Overridepublic ColorStateList getColorStateList(int id, Theme theme) throws NotFoundException {return mBase.getColorStateList(id, theme);}Overridepublic boolean getBoolean(int id) throws NotFoundException {return mBase.getBoolean(id);}Overridepublic int getInteger(int id) throws NotFoundException {return mBase.getInteger(id);}Overridepublic XmlResourceParser getLayout(int id) throws NotFoundException {return mBase.getLayout(id);}Overridepublic XmlResourceParser getAnimation(int id) throws NotFoundException {return mBase.getAnimation(id);}Overridepublic XmlResourceParser getXml(int id) throws NotFoundException {return mBase.getXml(id);}Overridepublic InputStream openRawResource(int id) throws NotFoundException {return mBase.openRawResource(id);}Overridepublic InputStream openRawResource(int id, TypedValue value) throws NotFoundException {return mBase.openRawResource(id, value);}Overridepublic AssetFileDescriptor openRawResourceFd(int id) throws NotFoundException {return mBase.openRawResourceFd(id);}Overridepublic void getValue(int id, TypedValue outValue, boolean resolveRefs) throws NotFoundException {mBase.getValue(id, outValue, resolveRefs);}Overridepublic void getValueForDensity(int id, int density, TypedValue outValue, boolean resolveRefs) throws NotFoundException {if (Build.VERSION.SDK_INT Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {mBase.getValueForDensity(id, density, outValue, resolveRefs);}}Overridepublic void getValue(String name, TypedValue outValue, boolean resolveRefs) throws NotFoundException {mBase.getValue(name, outValue, resolveRefs);}Overridepublic TypedArray obtainAttributes(AttributeSet set, int[] attrs) {return mBase.obtainAttributes(set, attrs);}Overridepublic DisplayMetrics getDisplayMetrics() {return mBase.getDisplayMetrics();}Overridepublic Configuration getConfiguration() {return mBase.getConfiguration();}Overridepublic int getIdentifier(String name, String defType, String defPackage) {return mBase.getIdentifier(name, defType, defPackage);}Overridepublic String getResourceName(int resid) throws NotFoundException {return mBase.getResourceName(resid);}Overridepublic String getResourcePackageName(int resid) throws NotFoundException {return mBase.getResourcePackageName(resid);}Overridepublic String getResourceTypeName(int resid) throws NotFoundException {return mBase.getResourceTypeName(resid);}Overridepublic String getResourceEntryName(int resid) throws NotFoundException {return mBase.getResourceEntryName(resid);}Overridepublic void parseBundleExtras(XmlResourceParser parser, Bundle outBundle) throws XmlPullParserException, IOException {mBase.parseBundleExtras(parser, outBundle);}Overridepublic void parseBundleExtra(String tagName, AttributeSet attrs, Bundle outBundle) throws XmlPullParserException {mBase.parseBundleExtra(tagName, attrs, outBundle);} }SingleMixRes优先从插件加载资源找不到则从宿主加载资源 public class SingleMixRes extends ResourcesWrapper{private Resources mHostResources;public SingleMixRes(Resources hostResources, Resources pluginResources) {super(pluginResources);mHostResources hostResources;}Overridepublic CharSequence getText(int id) throws NotFoundException {try {return super.getText(id);} catch (NotFoundException e) {return mHostResources.getText(id);}}Overridepublic String getString(int id) throws NotFoundException {try {return super.getString(id);} catch (NotFoundException e) {return mHostResources.getString(id);}}Overridepublic String getString(int id, Object... formatArgs) throws NotFoundException {try {return super.getString(id,formatArgs);} catch (NotFoundException e) {return mHostResources.getString(id,formatArgs);}}Overridepublic float getDimension(int id) throws NotFoundException {try {return super.getDimension(id);} catch (NotFoundException e) {return mHostResources.getDimension(id);}}Overridepublic int getDimensionPixelOffset(int id) throws NotFoundException {try {return super.getDimensionPixelOffset(id);} catch (NotFoundException e) {return mHostResources.getDimensionPixelOffset(id);}}Overridepublic int getDimensionPixelSize(int id) throws NotFoundException {try {return super.getDimensionPixelSize(id);} catch (NotFoundException e) {return mHostResources.getDimensionPixelSize(id);}}Overridepublic Drawable getDrawable(int id) throws NotFoundException {try {return super.getDrawable(id);} catch (NotFoundException e) {return mHostResources.getDrawable(id);}}TargetApi(Build.VERSION_CODES.LOLLIPOP)Overridepublic Drawable getDrawable(int id, Theme theme) throws NotFoundException {try {return super.getDrawable(id, theme);} catch (NotFoundException e) {return mHostResources.getDrawable(id,theme);}}Overridepublic Drawable getDrawableForDensity(int id, int density) throws NotFoundException {try {return super.getDrawableForDensity(id, density);} catch (NotFoundException e) {if (Build.VERSION.SDK_INT Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {return mHostResources.getDrawableForDensity(id, density);} else {return null;}}}TargetApi(Build.VERSION_CODES.LOLLIPOP)Overridepublic Drawable getDrawableForDensity(int id, int density, Theme theme) {try {return super.getDrawableForDensity(id, density, theme);} catch (Exception e) {return mHostResources.getDrawableForDensity(id,density,theme);}}Overridepublic int getColor(int id) throws NotFoundException {try {return super.getColor(id);} catch (NotFoundException e) {return mHostResources.getColor(id);}}TargetApi(Build.VERSION_CODES.M)Overridepublic int getColor(int id, Theme theme) throws NotFoundException {try {return super.getColor(id,theme);} catch (NotFoundException e) {return mHostResources.getColor(id,theme);}}Overridepublic ColorStateList getColorStateList(int id) throws NotFoundException {try {return super.getColorStateList(id);} catch (NotFoundException e) {return mHostResources.getColorStateList(id);}}TargetApi(Build.VERSION_CODES.M)Overridepublic ColorStateList getColorStateList(int id, Theme theme) throws NotFoundException {try {return super.getColorStateList(id,theme);} catch (NotFoundException e) {return mHostResources.getColorStateList(id,theme);}}Overridepublic boolean getBoolean(int id) throws NotFoundException {try {return super.getBoolean(id);} catch (NotFoundException e) {return mHostResources.getBoolean(id);}}Overridepublic XmlResourceParser getLayout(int id) throws NotFoundException {try {return super.getLayout(id);} catch (NotFoundException e) {return mHostResources.getLayout(id);}}Overridepublic String getResourceName(int resid) throws NotFoundException {try {return super.getResourceName(resid);} catch (NotFoundException e) {return mHostResources.getResourceName(resid);}}Overridepublic int getInteger(int id) throws NotFoundException {try {return super.getInteger(id);} catch (NotFoundException e) {return mHostResources.getInteger(id);}}Overridepublic CharSequence getText(int id, CharSequence def) {try {return super.getText(id,def);} catch (NotFoundException e) {return mHostResources.getText(id,def);}}Overridepublic InputStream openRawResource(int id) throws NotFoundException {try {return super.openRawResource(id);} catch (NotFoundException e) {return mHostResources.openRawResource(id);}}Overridepublic XmlResourceParser getXml(int id) throws NotFoundException {try {return super.getXml(id);} catch (NotFoundException e) {return mHostResources.getXml(id);}}TargetApi(Build.VERSION_CODES.O)Overridepublic Typeface getFont(int id) throws NotFoundException {try {return super.getFont(id);} catch (NotFoundException e) {return mHostResources.getFont(id);}}Overridepublic Movie getMovie(int id) throws NotFoundException {try {return super.getMovie(id);} catch (NotFoundException e) {return mHostResources.getMovie(id);}}Overridepublic XmlResourceParser getAnimation(int id) throws NotFoundException {try {return super.getAnimation(id);} catch (NotFoundException e) {return mHostResources.getAnimation(id);}}Overridepublic InputStream openRawResource(int id, TypedValue value) throws NotFoundException {try {return super.openRawResource(id,value);} catch (NotFoundException e) {return mHostResources.openRawResource(id,value);}}Overridepublic AssetFileDescriptor openRawResourceFd(int id) throws NotFoundException {try {return super.openRawResourceFd(id);} catch (NotFoundException e) {return mHostResources.openRawResourceFd(id);}} }更新Activity的资源 参考方式一 两种方式注意事项 打包出的插件apk需要去除第三方smali代码否则可能会报资源问题代码更新与资源更新最好同步预防id对应不上 附录 修改资源id冲突及去除第三方smali文件工具
http://www.hkea.cn/news/14563935/

相关文章:

  • 诚聘网站开发网站建设的主要步骤有哪些
  • 济宁商城网站建设python可以做网站前台么
  • 邯郸网站建设选哪家好iis 网站 端口
  • 网站建设哪里学app推广团队
  • 建设银行银行号查询网站海外免费网站推广有哪些
  • 属于c2c的网站有哪些做公司网站报价
  • 杭州网络科技网站腾讯云网站建设视频教程
  • 怎么套模板做网站h5网站要多久
  • 求个国外在线网站白河网站制作
  • 国家企业信息公示信息官网网站原创内容优化
  • cnetos 做网站服务网络推广的优化方法
  • 台州网站推广山西大同专业网站建设制作价格
  • flash cms网站源码网站攻击一般有那些
  • 个人网页制作与网站建设网站建设有模板自己能制作
  • 建设一个跟京东一样的网站网页制作培训学费
  • 宁波网站设计相信荣胜网络建e网卧室设计效果图
  • 海门建设厅网站网站建设包含项目
  • 做页面设计的网站网站开发工程师中级高级
  • 网站销售策划网站的版式
  • 外贸网址建站朋友圈广告怎么投放
  • 网站的关键词在哪里设置深圳网站商城建设
  • 搜狗网站优化软件论坛网站制作
  • 网站建设如何算成本快照网站
  • 全运会网站建设方案欧莱雅的网络营销策划方案
  • 开发企业小程序公司永康好口碑关键词优化
  • 点了网站域名会跳转外网域名
  • 网站建设毕业设计文献综述深圳网站设计比较好的公司有哪些
  • 网站开发用什么编辑语言好网站服务器暂时不可用怎么办
  • 做封面的免费网站wordpress文404
  • 做网站被骗预付款怎么办网站远程图片