Fork me on GitHub
chenzhenlindx的博客

静待花开


  • 首页

  • 关于

  • 标签

  • 分类

  • 归档

Android开启网络adb调试

发表于 2018-01-27 | 分类于 调试
  • 首先开启手机的USB调试并且使用USB连接电脑
  • 在终端执行adb tcpip 5555:

    1
    2
    C:\Users\LENOVO>adb tcpip 5555
    restarting in TCP mode port: 5555
  • 在终端执行adb connect 192.168.2.106:

    1
    2
    C:\Users\LENOVO>adb connect 192.168.2.106
    connected to 192.168.2.106:5555
  • 如果要断开连接
    在终端执行adb disconnect:

    1
    2
    C:\Users\LENOVO>adb disconnect
    disconnected everything

Inspect Code常见问题

发表于 2018-01-24 | 分类于 重构

Empty 'catch' block 空的catch代码块

问题:发生错误程序没有任何反应,不方便定位问题

try {
    ...
} catch (Exception e) {

}

Unused import

问题:Ctrl+Alt+O 处理即可

android studio生成aar包并在其他工程引用aar包

发表于 2018-01-23 | 分类于 重构

1、aar包是android studio下打包android工程中src、res、lib后生成的aar文件,aar包导入其他android studio 工程后,其他工程可以方便引用源码和资源文件
2、生成aar包的步骤:
①.用android studio打开一个工程,然后新建一个Module,新建Module时候选择Android Library,后面按新建普通工程操作;
②.在新建的Module中编写完代码后,接下来编译整个工程后就会自动生成aar包,包的路径在新建的Module ==》 build ===》outputs ==>aar目录下
3、其他androidstudio工程引用aar包
①.将aar包复制到lib目录下
②.配置build.gradle文件:
加入

1
2
3
4
5
6
7
8
9
10
repositories {
flatDir {
dirs 'libs'
}
}
dependencies {
...
compile(name:'auil-debug', ext:'aar')
...
}

③.编译一次工程
以上操作成功后可以在扩展包下看到被引用的aar包文件

Android String.xml 相关

发表于 2018-01-22 | 分类于 重构

动态显示

%n$ms:代表输出的是字符串,n代表是第几个参数,设置m的值可以在输出之前放置空格
%n$md:代表输出的是整数,n代表是第几个参数,设置m的值可以在输出之前放置空格
%n$mf:代表输出的是浮点数,n代表是第几个参数,设置m的值可以控制小数位数,如m=2.2时,输出格式为00.00

%1$s
1
<string name="loading">离下班回家还剩%1$s分钟</string>
1
2
String temp = getResources().getString(R.string.loading);
String timeTip = String.format(temp,38);

结果:离下班回家还剩38分钟

%1$3s
1
<string name="loading">离下班回家还剩%1$4s分钟</string>
1
2
String temp = getResources().getString(R.string.loading);
String timeTip = String.format(temp,38);

结果:离下班回家还剩 38分钟
注:m设置为4只有2个空格

%1$2.2f
1
<string name="loading">离下班回家还剩%1$2.2f分钟</string>
1
2
String temp = getResources().getString(R.string.loading);
String timeTip = String.format(temp,1234.123);

结果:离下班回家还剩1234.12分钟

%的显示

使用%%来显示一个%

1
<string name="loading">离下班回家还剩%1$2.2f%%分钟</string>

1
2
String temp = getResources().getString(R.string.loading);
String timeTip = String.format(temp,34.123);

结果:离下班回家还剩34.12%分钟

空格的显示

&#8194;半个中文字
1
<string name="num">今日&#8194;&#8194;&#8194;&#8194;工单总数</string>

结果:

Json和Gson的使用

发表于 2018-01-21 | 分类于 Json
泛型的使用

通常使用new TypeToken<XXX>(){}来获取Type之后转换

Type type = new TypeToken<Subsys<FireData>>(){}.getType();
subsys.Fire=new Gson().fromJson(obj.optString("Fire"),type);

重构——引入Databinding

发表于 2018-01-20 | 分类于 重构
添加DataBinding支持

在Android Studio上使用,需要在module级别的build.gradle上添加对DataBinding的支持

1
2
3
4
5
6
android {
....
dataBinding {
enabled = true
}
}

布局文件

DataBinding的layout files和普通的非DataBinding布局文件是有一些区别的,下面是一个基础的使用了DataBinding的布局文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

<data>
<variable
name="user"
type="com.example.User" />
</data>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.firstName}" />

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.lastName}" />
</LinearLayout>
</layout>

事件处理
点击事件onClick

android:onClick="@{()->viewModel.logout()}

1
2
3
4
5
6
7
8
9
10
11
<Button
android:id="@+id/log_out"
android:layout_width="268dp"
android:layout_height="32dp"
android:layout_centerHorizontal="true"
android:layout_marginTop="40dp"
android:onClick="@{()->viewModel.logout()}"
android:background="@drawable/round_corner_logout"
android:text="@string/log_out"
android:textColor="#ffffff"
android:textSize="14sp" />

ViewPager
setCurrentItem(int item)
  • 在ViewModel创建public ObservableInt mCurrentIndex = new ObservableInt();
  • 在xml关联app:currentItem="@{viewModel.mCurrentIndex}"
  • 通过设置mCurrentIndex的值,即可改变ViewPager的显示位置
    1
    2
    3
    public void setCurrentItem(int currentIndex) {
    mCurrentIndex.set(currentIndex);
    }
setAdapter(PagerAdapter adapter)
  • 在ViewModel创建public FragmentPagerAdapter mAdapter;
  • 在setViewModel前,需要初始化mAdapter
  • 在xml关联app:adapter="@{viewModel.mAdapter}"
setOnPageChangeListener(OnPageChangeListener listener)
  • 在ViewModel实现接口implements OnPageChangeListener
  • 重写OnPageChangeListener的方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public void onPageScrollStateChanged(int state) {

    }

    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }

    public void onPageSelected(int position) {
    mCurrentIndex.set(position);
    }
  • 在xml关联app:onPageChangeListener="@{viewModel}"

View的可见状态控制
  • 引入View <import type="android.view.View" />
  • 通过?:来控制显示
    1
    android:visibility="@{viewModel.isVisible?View.VISIBLE:View.GONE}"
颜色控制
  • 通过?:来控制显示
    1
    android:textColor="@{viewModel.isBlue?@color/blue:@color/gray}"
Include布局

Include这个布局标签在DataBinding布局里面使用有点特殊, 因为它需要我们传递绑定的方法和数据对象。比如我们有以下的include布局:

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<import type="android.view.View" />
<variable
name="viewModel"
type="com.zhhx.fragment.IbmsMainFragment" />
</data>
</layout>

那么我们在另一个xml引用时,就需要传递这个include需要绑定的方法和数据:

1
2
3
<include
layout="@layout/include_sub_system_airconditioner"
app:viewModel="@{viewModel}" />

ObservableField

使用ObservableField可以引用复杂的数据类型,如

1
public ObservableField<SubsysBean> subsysBean = new ObservableField<>();

在数据更新时,直接set即可,不需要对SubsysBean实现Bindable注解。

1
subsysBean.set(info);

Databinding自动判空

使用时不需要判空,如:

1
2
info.Video.getData().setObjList(null);
subsysBean.set(info);

1
2
3
<TextView
...
android:text="@{String.valueOf(viewModel.subsysBean.Video.data.ObjList.get(2).ValidCount)}" />

查看源码可知,虽然进行了判空,但是对数组越界没有进行处理,所以要 谨慎防止数组越界

1
2
3
4
5
6
if (viewModelSubsysBeanVideoDataGetObjList != null) {
// read viewModel.subsysBean.get().Video.data.getObjList().get(1)
viewModelSubsysBeanVideoDataGetObjListGetInt1 = viewModelSubsysBeanVideoDataGetObjList.get(1);
// read viewModel.subsysBean.get().Video.data.getObjList().get(2)
viewModelSubsysBeanVideoDataGetObjListGetInt2 = viewModelSubsysBeanVideoDataGetObjList.get(2);
}

TextView的int类型数值的显示

直接使用int类型会报错,可以调用String.valueOf()方法

<TextView
   ...
   android:text="@{String.valueOf(viewModel.subsysBean.Video.data.ObjList.get(2).ValidCount)}" />

重构智慧社区遇到的问题

发表于 2018-01-20 | 分类于 重构
transformNativeLibsWithStripDebugSymbolForDebug
1
2
Error:Execution failed for task ':zhhxProperty:transformNativeLibsWithStripDebugSymbolForDebug'.
> java.lang.NullPointerException (no error message)
解决方案:

将compileSdkVersion 19改成compileSdkVersion 27,即升级所有module的compileSdkVersion

程序包org.apache.http不存在
解决方案:

build.gradle中,在buildToolsVersion和defaultConfig之间添加如下代码

1
useLibrary 'org.apache.http.legacy'

FloatMath不存在

找不到符号FloatMath
符号: 方法 floor(float)
位置: 类 FloatMath

解决方案:

将FloatMath.floor()改成Math.floor()

setLatestEventInfo

Error:(403, 25) 错误: 找不到符号
符号: 方法 setLatestEventInfo(Context,String,String,PendingIntent)
位置: 类型为Notification的变量 notification

解决方案:

将notification.setLatestEventInfo(context, title, message, pi);
改成showNotification(pi,title,message);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private void showNotification(PendingIntent contentIntent, String contentTitle, String contentText) {
//2、发布到通知栏,让监听者能点击
//获取NotificationManager实例
NotificationManager notifyManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
//实例化NotificationCompat.Builde并设置相关属性
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setContentIntent(contentIntent)
.setDefaults(Notification.DEFAULT_ALL)
//设置小图标
.setSmallIcon(R.mipmap.ic_launcher)
//设置通知标题
.setContentTitle(TextUtils.isEmpty(contentTitle) ? getResources().getString(R.string.app_name) : contentTitle)
.setAutoCancel(true)
//设置通知内容
.setContentText(contentText);
//通过builder.build()方法生成Notification对象,并发送通知,id=1
notifyManager.notify(1, builder.build());
}

找不到Frganment的getContext()方法。

Error:(197, 28) 错误: 找不到符号
符号: 方法 getContext()
位置: 类 ComplaintClosedFragment

解决方法:

改用getActivity()方法。

找不到ViewPager的addOnPageChangeListener()方法。

Error:(428, 23) 错误: 找不到符号
符号: 方法 addOnPageChangeListener(ComplaintFragment.TabOnPageChangeListener)
位置: 类型为ViewPager的变量 mViewPager

解决方法:

改用setOnPageChangeListener()方法。

javaPreCompileDebug报错
1
2
3
4
5
Error:Execution failed for task ':zhhxProperty:javaPreCompileDebug'.
> Annotation processors must be explicitly declared now. The following dependencies on the compile classpath are found to contain annotation processor. Please add them to the annotationProcessor configuration.
- realm-android-0.87.4.jar (realm-android-0.87.4.jar)
Alternatively, set android.defaultConfig.javaCompileOptions.annotationProcessorOptions.includeCompileClasspath = true to continue with previous behavior. Note that this option is deprecated and will be removed in the future.
See https://developer.android.com/r/tools/annotation-processor-error-message.html for more details.
解决方案:

在defaultconfig添加

1
2
3
4
5
javaCompileOptions {
annotationProcessorOptions {
includeCompileClasspath true
}
}

android.dexOptions.incremental deprecated
1
Warning:The `android.dexOptions.incremental` property is deprecated and it has no effect on the build process.
解决方案:

删除如下代码的incremental属性

1
2
3
4
dexOptions {
incremental true
javaMaxHeapSize "4g"
}

transformDexArchiveWithExternalLibsDexMergerForDebug
1
2
Error:Execution failed for task ':zhhxProperty:transformDexArchiveWithExternalLibsDexMergerForDebug'.
> com.android.builder.dexing.DexArchiveMergerException: Unable to merge dex
解决方案:

通过aar引用了某工程,又通过module引用了,删掉module引用即可。

TODO

1、图片框架改造;
http://highlightjs.readthedocs.io/en/latest/css-classes-reference.html

Android 代码规范 - 命名规范

发表于 2018-01-20 | 分类于 命名规范

Layout

Layout的命名规则需要和使用他们的组件对应,方便查找和维护,比如我们在创建一个用户信息的UserInfoActivity,对应的Layout的命名就应该是activity_user_info.xml。对应Andorid组件的Layout命名规则:

  • Activity -> activity_user_info.xml
  • Fragment -> fragment_sign_up.xml
  • Dialog -> dialog_change_password.xml
  • AdapterView Item -> item_user.xml
  • include -> include_stats_bar.xml

czy1121_update应用笔记(二)——Android客户端

发表于 2018-01-16 | 分类于 第三方库

最近做的一个APP需要检测更新,以前都是自己写的,这次决定使用别人封装好的一个库。

czy1121/update
清晰灵活简单易用的应用更新库

第一步,需要搭建一个检测更新的服务。详见
czy1121_update应用笔记(一)——搭建服务

第二步,就是编写Android客户端代码了。

  • 创建Android工程;
  • 导入相关的库

    • czy1121/update

      1
      2
      3
      4
      5
      6
      repositories { 
      maven { url "https://jitpack.io" }
      }
      dependencies {
      implementation 'com.github.czy1121:update:1.1.1'
      }
    • afollestad/material-dialogs

      1
      2
      3
      4
      dependencies {
      implementation 'com.afollestad.material-dialogs:core:0.9.5.0'
      implementation 'com.afollestad.material-dialogs:commons:0.9.5.0'
      }
    • Blankj/AndroidUtilCode

      1
      2
      3
      dependencies {
      implementation 'com.blankj:utilcode:1.9.2'
      }

    需要设置Application并且初始化Utils

    1
    2
    3
    4
    5
    6
    7
    public class MyApplication extends Application {
    @Override
    public void onCreate() {
    super.onCreate();
    Utils.init(this);
    }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <application
    android:name=".MyApplication"
    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>
    </application>
    • 修改app下的build.gradle
    1
    2
    3
    4
    5
    6
    7
    8
    defaultConfig {
    applicationId "cn.czl.updatedemo"
    minSdkVersion 16
    targetSdkVersion 22
    versionCode 1
    versionName "1.0"
    testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    1
    2
    3
    4
    compileOptions {
    sourceCompatibility 1.8
    targetCompatibility 1.8
    }
    • 修改xml布局文件,新增一个TextView用于显示版本,新增一个Button用于主动更新
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    <?xml version="1.0" encoding="utf-8"?>
    <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="cn.czl.updatedemo.MainActivity">

    <TextView
    android:id="@+id/tv_version"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Hello World!"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

    <Button
    android:id="@+id/button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="30dp"
    android:text="检查更新"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/tv_version" />

    </android.support.constraint.ConstraintLayout>
    • 在MainActivity中编写更新方法,自定义下载提示框、进度框。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      /**
      * 根据 agent.getInfo() 显示更新版本对话框,具体可参考 {@link UpdateAgent.DefaultUpdatePrompter}
      *
      * @param isManual
      */
      public void update(boolean isManual) {
      // 设置默认更新接口地址与渠道
      UpdateManager.setUrl("http://10.129.51.27:8080/app/check", "yyb");
      // 进入应用时查询更新
      UpdateManager.create(this)
      //自定义更新提示框
      .setPrompter(agent -> {
      UpdateInfo updateInfo = agent.getInfo();
      String size = Formatter.formatShortFileSize(MainActivity.this, updateInfo.size);
      new MaterialDialog.Builder(MainActivity.this)
      .title("应用更新")
      .content(R.string.update_content, updateInfo.versionName, size, updateInfo.updateContent)
      .negativeText("以后再说")
      .negativeColor(getResources().getColor(R.color.blue))
      .positiveText("立即更新")
      .positiveColor(getResources().getColor(R.color.blue))
      .onPositive((dialog, which) -> agent.update())
      .show();
      })
      //更新失败给出提示
      .setOnFailureListener(error -> ToastUtils.showShort(error.toString()))
      //设置下载进度条
      .setOnDownloadListener(new OnDownloadListener() {
      private MaterialDialog dialog;

      @Override
      public void onStart() {
      dialog = new MaterialDialog.Builder(MainActivity.this)
      .content("下载中")
      .progress(false, 100, true)
      .cancelable(false)
      .show();
      }

      @Override
      public void onProgress(int progress) {
      if (null != dialog) {
      dialog.setProgress(progress);
      }
      }

      @Override
      public void onFinish() {
      if (dialog != null) {
      dialog.dismiss();
      dialog = null;
      }
      }
      })
      .setManual(isManual)
      //开始更新
      .check();
      }
    • 配置网络权限ACCESS_NETWORK_STATE和INTERNET

    1
    2
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />

    -安装运行,即可看到如下2个界面:
    更新弹窗
    下载进度

注意: 本地apk和服务器apk需要签名相同,都需要release版本才能正常更新。
apk旧版本
apk新版本

czy1121_update应用笔记(一)——搭建服务

发表于 2018-01-16 | 分类于 第三方库

最近做的一个APP需要检测更新,以前都是自己写的,这次决定使用别人封装好的一个库。

czy1121/update
清晰灵活简单易用的应用更新库

第一步,需要搭建一个检测更新的服务。这里直接在之前写的一个库的基础上修改。

chenzhenlindx/SpringBootDemo
清晰灵活简单易用的应用更新库
首先导入此项目,或者按照说明创建项目。

要实现的效果为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
url:http://example.com/check?package=ezy.demo.update&version=123&channel=yyb
method:get
response:
{
"hasUpdate": true,
"isSilent": false,
"isForce": false,
"isAutoInstall": true,
"isIgnorable": true,
"versionCode": 2,
"versionName": "v2.0.2018-1-16",
"updateContent": "1、修改了bug1;\r\n2、修改了bug2;\r\n3、新增了某个功能。",
"url": "http://10.129.51.27:8080/apk/apk2018-1-15.apk",
"md5": "34db53f031fccf92b779e0d160ef37c1",
"size": 1824234
}

1、在package com.example.demo.domain创建UpdateInfo.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class UpdateInfo {
// 是否有新版本
public boolean hasUpdate = false;
// 是否静默下载:有新版本时不提示直接下载
public boolean isSilent = false;
// 是否强制安装:不安装无法使用app
public boolean isForce = false;
// 是否下载完成后自动安装
public boolean isAutoInstall = true;
// 是否可忽略该版本
public boolean isIgnorable = true;

public int versionCode;
public String versionName;
public String updateContent;

public String url;
public String md5;
public long size;
}

2、在resources目录下创建static/apk文件夹,将新版本apk复制到此目录

启动服务后,点击 http://10.129.51.27:8080/apk/apk2018-1-15.apk 弹窗文件下载框,表示文件位置正确。

3、创建AppConttroller.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
package com.example.demo.controller;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.math.BigInteger;
import java.security.MessageDigest;

import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.example.demo.domain.UpdateInfo;

@RequestMapping("/app")
@RestController
public class AppConttroller {
/**
* http://10.129.51.27:8080/app/check?package=cn.czl.updatedemo&version=1&channel=main
*
* @return
* @throws FileNotFoundException
*/
@RequestMapping(value = "/check", method = RequestMethod.GET)
public UpdateInfo check(@RequestParam(name = "package", required = true) String pkg,
@RequestParam(name = "version", required = true) int version,
@RequestParam(name = "channel", required = true) String channel) throws FileNotFoundException {
UpdateInfo updateInfo = new UpdateInfo();
if (version > 1) {
updateInfo.hasUpdate = false;
} else {
updateInfo.hasUpdate = true;
updateInfo.versionCode = 2;
updateInfo.versionName = "v2.0.2018-1-16";
updateInfo.updateContent = "1、修改了bug1;\r\n" + "2、修改了bug2;\r\n" + "3、新增了某个功能。";

updateInfo.url = "http://10.129.51.27:8080/apk/apk2018-1-15.apk";
File file = ResourceUtils.getFile("classpath:static/apk/apk2018-1-15.apk");
updateInfo.md5 = md5(file);
updateInfo.size = file.length();
}
return updateInfo;
}

public static String md5(File file) {
MessageDigest digest = null;
FileInputStream fis = null;
byte[] buffer = new byte[1024];
try {
if (!file.isFile()) {
return "";
}
digest = MessageDigest.getInstance("MD5");
fis = new FileInputStream(file);
while (true) {
int len;
if ((len = fis.read(buffer, 0, 1024)) == -1) {
fis.close();
break;
}
digest.update(buffer, 0, len);
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
BigInteger var5 = new BigInteger(1, digest.digest());
return String.format("%1$032x", new Object[] { var5 });
}
}

在浏览器访问:
http://10.129.51.27:8080/app/check?package=cn.czl.updatedemo&version=1&channel=main
即可得到预想的json。
注意:

  1. 正常情况我们应该apk使用表单上传,更新信息应该从表单获取;
  2. 代码直接当version>1判断无更新,实际上应该查询数据库最新版本进行比较;
  3. md5是获取apk文件的md5,而不是打包签名文件的md5,具体的md5获取代码如上。

至此,服务端代码编写完成,详情可参考
czy1121Update/SpringBoot

12
chenzhenlindx

chenzhenlindx

Android开发者

14 日志
8 分类
13 标签
© 2018 chenzhenlindx
由 Hexo 强力驱动
|
主题 — NexT.Pisces v5.1.4