当前位置: 首页>移动开发>正文

Android Studio 命令行编译模块 android studio命令行工具

简介:

关于热修复的介绍现在网上有很多,所以在此我就不过多BB,此篇博客的特点有两个,首先,这是一个针对Android studio3.0用户的博客,其次,这里采用的是命令行的方式,这是方式在工作中并不经常使用,相反,在工作中基本都是使用gradle配置的方式,但是命令行的方式相比于gradle是简单很多的,所以这就这是一个入门级的tinker集成,意在让大家了解tinker这个相对最为全面的热修复框架(高手请绕路,前方低能)。

1、在gradle.properties中配置我们tinker的版本。这种配置方式就相当于定义一个变量,用于指定我们导入依赖的版本,这样对于同一框架的多个依赖可以进行很好的版本控制。

粘贴板:TINKER_VERSION=1.9.0

Android Studio 命令行编译模块 android studio命令行工具,Android Studio 命令行编译模块 android studio命令行工具_ide,第1张

2、module中导入依赖,在这里可以看到我们刚刚定义的变量在这里得以使用

粘贴板:

//可选,用于生成application类
    implementation("com.tencent.tinker:tinker-android-lib:${TINKER_VERSION}") { changing = true }
    //tinker的核心库
    annotationProcessor("com.tencent.tinker:tinker-android-anno:${TINKER_VERSION}") { changing = true }

    compileOnly("com.tencent.tinker:tinker-android-anno:${TINKER_VERSION}") { changing = true }

    implementation "com.android.support:multidex:1.0.2"


Android Studio 命令行编译模块 android studio命令行工具,Android Studio 命令行编译模块 android studio命令行工具_加载_02,第2张

3、创建一个管理类,来管理我们Tinker中所有的api,方便我们的使用和以后对其他工程的植入。代码都有注释,这里就直接上代码了

package com.jiaxin.tinkerthree.tinker;

import android.content.Context;

import com.tencent.tinker.lib.tinker.Tinker;
import com.tencent.tinker.lib.tinker.TinkerInstaller;
import com.tencent.tinker.loader.app.ApplicationLike;

/**
 * Created by Zzw on 2017/12/24.14:06
 *
 * @function 对Tinker的所有api做一层封装
 */

public class TinkerManger {

    //判断tinker是否已经初始化
    private static boolean isInstalled = false;

    private static ApplicationLike mAppLike;

    /**
     * 由外部调用完成tinker 的初始化
     * @param applicationLike
     */
    public static void instaillTinker(ApplicationLike applicationLike){
        mAppLike = applicationLike;
        if (isInstalled){
            return;
        }
        TinkerInstaller.install(mAppLike);//完成tinker初始化
        isInstalled = true;
    }

    /**
     * 完成patch文件加载
     * @param path
     */
    public static  void loadPatch(String path){
        if (Tinker.isTinkerInstalled()){
            TinkerInstaller.onReceiveUpgradePatch(getApplicationContext(), path);
        }
    }

    /**
     * 通过applicationLike获取context
     * @return
     */
    private static Context getApplicationContext(){
        if (mAppLike != null){
            return mAppLike.getApplication().getApplicationContext();
        }
        return null;
    }
}


3、根据官方的要求我们要使用ApplicationLike这个类,来生成application,所以我们这里创建一个类来继承他

package com.jiaxin.tinkerthree.tinker;

import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.support.multidex.MultiDex;

import com.tencent.tinker.anno.DefaultLifeCycle;
import com.tencent.tinker.loader.app.ApplicationLike;
import com.tencent.tinker.loader.shareutil.ShareConstants;

/**
 * Created by Zzw on 2017/12/24.14:11
 */

@DefaultLifeCycle(application = ".MyTinkerApplication" ,
        flags = ShareConstants.TINKER_ENABLE_ALL , loadVerifyFlag = false)
public class CustomTinkerLike extends ApplicationLike {
    public CustomTinkerLike(Application application, int tinkerFlags, boolean tinkerLoadVerifyFlag, long applicationStartElapsedTime, long applicationStartMillisTime, Intent tinkerResultIntent) {
        super(application, tinkerFlags, tinkerLoadVerifyFlag, applicationStartElapsedTime, applicationStartMillisTime, tinkerResultIntent);
    }

    @Override
    public void onBaseContextAttached(Context base) {
        super.onBaseContextAttached(base);

        MultiDex.install(base);//使应用支持分包

        TinkerManger.instaillTinker(this);
    }
}

注意这里我们使用了 一个注解,注解中后面两个参数可以认为是固定参数,第一个是我们指定的生成Application类的名字,这里我们叫他"MyTinkerApplication"

以上配置都完毕后我们编译整个工程,tinker的注解就会为我们生成一个MyTinkerApplication类。

4、清单文件中配置

这里的配置就是指定application为我们刚刚生成的"MyTinkerApplication",还有一个TINKER_ID的配置,这个主要是因为tinker在加载补丁文件的时候会只能的判断当前版本和补丁版本是否一致,如果不一致就会认为此补丁文件无效,就不会加载,所以我们这里做测试的话两次apk生成的时候只要这里不该动就好了

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.jiaxin.tinkerthree">

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

    <application
<!-- 此处指定application为tinker为我们生成的application -->
        android:name=".tinker.MyTinkerApplication"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <meta-data
            android:name="UMENG_CHANNEL"
            android:value="${UMENG_CHANNEL_VALUE}" />
<!-- 此处为tinker配置当前的应用版本 -->
        <meta-data
            android:name="TINKER_ID"
            android:value="tinker_id_123456"
            />
    </application>

</manifest>


5、以上步骤完成后,我们tinker的配置工作基本也就完成了,接下来只要使用我们的tinker管理类,生成两个不同版本的apk即可,这里因为tinker是支持布局文件的修改的,所以我模拟了点击一个按钮增加一个按钮的功能, 下面是我activity中的使用,布局就不写了哈

package com.jiaxin.tinkerthree;

import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import com.jiaxin.tinkerthree.tinker.TinkerManger;

import java.io.File;

public class MainActivity extends AppCompatActivity {

    //log key
    public static final String TAG = "myLog";

    //file's end name
    private static final String FILE_END = ".apk";

    //patch file's path
    private String mPatchDir;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mPatchDir = Environment.getExternalStorageDirectory().getAbsolutePath();

        Log.d(TAG, "onCreate: " + mPatchDir);
        File file = new File(mPatchDir);
        if (file.exists()){
            Toast.makeText(this, "文件存在", Toast.LENGTH_SHORT).show();
        }else{
            boolean mkdirs = file.mkdir();
            Toast.makeText(this, mkdirs ? "创建成功" : "创建失败", Toast.LENGTH_SHORT).show();
        }
    }

    /**
     * @click
     * @param view
     * load tinker patch for application
     */
    public void loadPatch(View view){
        TinkerManger.loadPatch(getPathName());
    }

    //get tinker patch fileName
    private String getPathName() {
        return mPatchDir.concat("/tinker").concat(FILE_END);
    }
}


6、好,接下来我们只要改变布局文件生成两个版本不同的apk即可,我这里是在新的apk中添加了一个按钮,所以old版本的apk只有一个按钮,用于点击加载补丁文件,new版本的apk中在第一个按钮的基础上又添加了一个按钮。

7、两个apk版本生成成功后接下来就是生成补丁apk,我们采用的是命令行的方式,所以当然是要使用tinker为我们提供的工具,我们将所有要使用到的文件和新旧两个版本的apk文件以及jks签名文件放在同一个目录下(建议新建一个文件夹),然后打开命令行工具进入该文件夹,执行jar文件:

java -jar  tinker-patch-cli-1.7.7.jar

Android Studio 命令行编译模块 android studio命令行工具,Android Studio 命令行编译模块 android studio命令行工具_ide_03,第3张

可以看到tinker提示我们该命令需要一堆参数,可以看到新旧版本apk文件我们已经准好了,只差一个tinker_config文件,我们打开这个文件,修改其中的loader为我们的application的名字,修改issue配置为我们签名的配置和密码

Android Studio 命令行编译模块 android studio命令行工具,Android Studio 命令行编译模块 android studio命令行工具_ide_04,第4张

Android Studio 命令行编译模块 android studio命令行工具,Android Studio 命令行编译模块 android studio命令行工具_android_05,第5张

8、配置完毕后,打开命令行工具,指定好参数在执行刚刚的命令就可以在output文件夹中看到tinker为我们生成的apk文件,将patch_signed.apk(签名版的)这个文件改为我们一开始指定的文件名称(我这里是tinker.apk),再将其拷贝到我们一开始指定的路径,我这里指定的是sd下默认路径,安装old版本apk整个过程就完成了~~。

9、打开安装好的旧版本apk,点击按钮,程序会闪退,再次打开就会发现后添加的按钮就已经被添加上去了,这里闪退不用担心,这是tinker默认的设置,因为tinker在加载补丁文件完毕后,不重新启动是不会生效的。这个也可以通过配置来更改,具体可以通过查看相关文档来实现。

 


https://www.xamrdz.com/mobile/4df1964553.html

相关文章: