Replugin2.2.4 Demo,包含Host,以及Plugins两部分

奇虎360Replugin的相关介绍已经很多了。这是一个简单的demo。更新下载平台用的公司内网。大家集成Replugin以后,也需要服务端配合,做一个插件管理系统,这样才能好好玩。

关于host部分

贴图好呢?还是代码好呢?

1.在project中的build.gradle中配置:

buildscript {
    
    repositories {
        google()
        jcenter()

    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.3.3'
        classpath 'com.qihoo360.replugin:replugin-host-gradle:2.2.4'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

2.在app的build.gradle

apply plugin: 'replugin-host-gradle'

 这句要添加到android{

   。。。。。。。

}后面

repluginHostConfig {
    /**
     * 是否使用 AppCompat      * 不需要个性化配置时,无需添加
     */
    useAppCompat = true
//    /**
//     * 背景不透明的坑的数量
//     * 不需要个性化配置时,无需添加
//     */
//    countNotTranslucentStandard = 6
//    countNotTranslucentSingleTop = 2
//    countNotTranslucentSingleTask = 3
//    countNotTranslucentSingleInstance = 2
}

3.dependencies{ 。。。。}中添加

compile 'com.qihoo360.replugin:replugin-host-lib:2.2.4'

4.application

package zyc.com.replugin.application;

import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;

import com.qihoo360.replugin.RePlugin;
import com.qihoo360.replugin.RePluginApplication;
import com.qihoo360.replugin.RePluginCallbacks;
import com.qihoo360.replugin.RePluginConfig;
import com.qihoo360.replugin.RePluginEventCallbacks;

import zyc.com.replugin.BuildConfig;
import zyc.com.replugin.util.PluginUpdateUtil;

/**
 * Created by zhangyc on 2018/5/7.
 */

public class MainApp extends RePluginApplication {
//    @Override
//    protected void attachBaseContext(Context base) {
//        super.attachBaseContext(base);
//
//        // FIXME 允许接收rpRunPluginGradle Task,发布时请务必关掉,以免出现问题
//        RePlugin.enableDebugger(base, BuildConfig.DEBUG);
//    }

//    @Override
//    public void onCreate() {
//        super.onCreate();
//        OkGo.getInstance().init(this);
//    }

    @Override
    protected RePluginConfig createConfig() {
        RePluginConfig c = new RePluginConfig();

        // 允许插件使用宿主类。默认为关闭        c.setUseHostClassIfNotFound(true);

        // FIXME RePlugin默认会对安装的外置插件进行签名校验,这里先关掉,避免调试时出现签名错误
        c.setVerifySign(!BuildConfig.DEBUG);

        // 针对安装失败等情况来做进一步的事件处理
        c.setEventCallbacks(new HostEventCallbacks(this));
        c.setMoveFileWhenInstalling(false);

        // FIXME 若宿主为Release,则此处应加上您认为"合法"的插件的签名,例如,可以写上"宿主"自己的。
        // RePlugin.addCertSignature("AAAAAAAAA");

        // Art上,优化第一次loadDex的速度
        // c.setOptimizeArtLoadDex(true);
        return c;
    }
    private class HostEventCallbacks extends RePluginEventCallbacks {

        private static final String TAG = "HostEventCallbacks";

        public HostEventCallbacks(Context context) {
            super(context);
        }

        @Override
        public void onInstallPluginFailed(String path, InstallResult code) {
            // FIXME 当插件安装失败时触发此逻辑。您可以在此处做打点统计,也可以针对安装失败情况做特殊处理            // 大部分可以通过RePlugin.install的返回值来判断是否成功
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "onInstallPluginFailed: Failed! path=" + path + "; r=" + code);
            }
            super.onInstallPluginFailed(path, code);
        }

        @Override
        public void onStartActivityCompleted(String plugin, String activity, boolean result) {
            // FIXME 当打开Activity成功时触发此逻辑,可在这里做一些APM、打点统计等相关工作
            super.onStartActivityCompleted(plugin, activity, result);
        }
    }

    @Override
    protected RePluginCallbacks createCallbacks() {
        return new UpdateRePluginCallbacks(this);
    }
    /***
     //这个回调在跳转的时候找不到目标Activity时,进行下载对应模块
    public class UpdateRePluginCallbacks extends RePluginCallbacks {

        public UpdateRePluginCallbacks(Context context) {
            super(context);
        }

        public boolean onPluginNotExistsForActivity(Context context, String plugin, Intent intent, int process) {
            if("host".equals(plugin)|| RePlugin.getPluginInfo(plugin)!=null){ //已按照
                Toast.makeText(MainApp.this,"不能这个样子的",Toast.LENGTH_SHORT).show();
            }else {
                PluginUpdateUtil updateUtil=new PluginUpdateUtil(context);
                updateUtil.installPlugin(context,intent,plugin);
            }
            return true;
        }
    }
}

5.本地插件版本 检查->下载->更新->安装->打开的逻辑实现

  /**
     * 检查插件
     */
    public void checkPlugin() {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
//        builder.sslSocketFactory(sslSocketFactory, trustAllCert);
        builder.connectTimeout(30, TimeUnit.SECONDS)
                .retryOnConnectionFailure(true);
//                .addInterceptor(loggingInterceptor);
        OkHttpClient okHttpClient = builder.build();
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(PublicContact.SERVER_IP)
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .client(okHttpClient)
                .build();
        VersionService tmp = retrofit.create(VersionService.class);
        tmp.getHotFix(PublicContact.APP_KEY_PLUGINUPDATE,PublicContact.FRAEWORK_VERSION).
                subscribeOn(Schedulers.io()).
                observeOn(AndroidSchedulers.mainThread()).
                subscribe(new Consumer<PublicResponseEntity<List<HotFixInfo>>>() {

            @Override
            public void accept(PublicResponseEntity<List<HotFixInfo>> hotfixs) throws Exception {
                Log.i(">>>",hotfixs.getMsg());
                List<HotFixInfo> needUpdatePlugins=new ArrayList<>();
                //本地插件信息列表
                List<PluginInfo> localPlugins = RePlugin.getPluginInfoList();
                if (0!=hotfixs.getCode()||null==hotfixs.getData()){
                    return;
                }
                for (HotFixInfo hotfit: hotfixs.getData()) {
                    //远程插件信息列表
                    int code=Integer.valueOf(hotfit.getNo());
                    Log.i(TAG,hotfit.getDownloadUrl());
                    //选出需要下载的插件,
                    //可以在这里进行相关的逻辑处理,可以根据pluginversioncode进行判断
                    for (PluginInfo pluginInfo:localPlugins){
                        //把本地版本低于服务端版本的放在一个集合中
                        if (pluginInfo.getVersion()<code){

                            needUpdatePlugins.add(hotfit);

                        }
                    }


                }


            }
        }, new Consumer<Throwable>() {
            @Override
            public void accept(Throwable throwable) throws Exception {
                Log.i("rx------",throwable.getMessage());
            }
        });

    }

下载:

/**
 * 下载
 */
public void downloadPlugin(final Context mcontext, String downloadUrl, final Intent intent, final String plugin){
    //监听下载进度
    final ProgressDialog dialog = new ProgressDialog(mcontext);
    dialog.setProgressNumberFormat("%1d KB/%2d KB");
    dialog.setTitle("下载");
    dialog.setMessage("正在下载,请稍后...");
    dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
    dialog.setCancelable(false);
    dialog.show();
    Retrofit.Builder retrofitBuilder = new Retrofit.Builder()
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .addConverterFactory(GsonConverterFactory.create())
            .baseUrl(downloadUrl+"/");
    OkHttpClient.Builder builder = ProgressHelper.addProgress(null);

    try {
        // 自定义一个信任所有证书的TrustManager,添加SSLSocketFactory的时候要用到
        final X509TrustManager trustAllCert = new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

            }

            @Override
            public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

            }

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[]{};
            }
        };
        final SSLSocketFactory sslSocketFactory = new SSLSocketFactoryCompat(trustAllCert);
        builder.sslSocketFactory(sslSocketFactory, trustAllCert);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
    DownloadApi retrofit = retrofitBuilder
            .client(builder.build())
            .build().create(DownloadApi.class);

    ProgressHelper.setProgressHandler(new DownloadProgressHandler() {
        @Override
        protected void onProgress(long bytesRead, long contentLength, boolean done) {
            Log.e("是否在主线程中运行", String.valueOf(Looper.getMainLooper() == Looper.myLooper()));
            Log.e("onProgress",String.format("%d%% done\n",(100 * bytesRead) / contentLength));
            Log.e("done",TAG + String.valueOf(done));
            dialog.setMax((int) (contentLength/1024));
            dialog.setProgress((int) (bytesRead/1024));

            if(done){
                dialog.dismiss();
            }
        }
    });

    retrofit2.Call<ResponseBody> call = retrofit.retrofitDownload(downloadUrl);
    call.enqueue(new Callback<ResponseBody>() {
        public PluginInfo info;

        @Override
        public void onResponse(retrofit2.Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) {
            try {
                InputStream is = response.body().byteStream();
                String appName=null;
                try {
                    appName=mcontext.getResources().getString(R.string.app_name);
                }catch (Exception e){
                    appName="tk";
                }

                File file = new File(Environment.getExternalStorageDirectory(), plugin+".apk");
                FileOutputStream fos = new FileOutputStream(file);
                BufferedInputStream bis = new BufferedInputStream(is);
                byte[] buffer = new byte[1024];
                int len;
                while ((len = bis.read(buffer)) != -1) {
                    fos.write(buffer, 0, len);
                    fos.flush();
                }
                fos.close();
                bis.close();
                is.close();
                //下载完成,自动安装插件
                String path=file.getAbsolutePath();
                installPlugins(path,intent);

            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onFailure(retrofit2.Call<ResponseBody> call, Throwable t) {

        }
    });

}

ok,目前就这样吧。

附上github的host地址,以及plugin的地址

git@github.com:zhangyc/RePluginHost.git
git@github.com:zhangyc/RePluginHost.git
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值