Leo's Blog

Stay Hungry Stay Foolish


  • Home

  • Archives

  • Categories

  • Tags

  • About

DeepLink

Posted on 2017-03-27   |   In Android   |   visitors

DeepLink 是什么

DeepLink 从字面意思可以理解为「深度链接」,那么 DeepLink 在 Android 开发中有什么作用呢?简单来说,可以用这种技术实现 web 页面点击一个链接跳转至 APP 指定的某一页面。这种技术的好处是可以为我们的 APP 导流。举个例子,我们公司是做一个房产平台的,如果用户在浏览器上看到新房列表的信息,并且手机上已经安装了应用的话,便可以直接跳转到 APP 的房产列表页面,原生页面在体验和功能上当然是要比 H5 页面强多了。如果此时没有安装应用可以直接跳转至下一个 H5 页面或者提示用户跳转到应用市场下载应用。

如何使用 DeepLink

我们的应用使用的是 Scheme 的方式来实现的,废话不多说,来看看正确的使用姿势。以我自己的项目为例。我们需要在清单文件 manifest 中添加 intent-filter。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<activity
android:name=".common.activity.WebStarterActivity"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="app.xxx.com"
android:scheme="openxxx" />
<data
android:host="app.xxx.com"
android:scheme="tel" />
</intent-filter>
</activity>

在对应 Activity 中的代码如下

1
2
3
4
5
if (getIntent() != null && getIntent().getData() != null) {
String refer = getIntent().getData().getQueryParameter("refer");
String path = getIntent().getData().getPath();
...
}

中间省去了业务逻辑代码,看到这里大家可能不太明白 Activiy 中的代码是什么意思,这里要简单的说一下 URL Scheme 协议的格式。

URL Scheme 协议格式

以我自己项目中定的协议为例,一个完整的 URL Schema 协议格式:

openxxx://app.xxx.com/newhouselist?city_id=xxxx&refer=xxxx

上面包含了 scheme、host、path、query。

  • openxxx 代表该 Scheme 协议名称(scheme)
  • app.xxx.com 代表 Scheme 作用于哪个地址域(host)
  • newhouselist 代表 Scheme 指定的页面(path)
  • city_id 代表传递的参数(query)

然后我们可以在 Activity 中获取 path 再跳转至对应的页面,并且可以通过 getQueryParameter() 方法来获取参数来传递给要跳转的页面。

Read more »

解决联网下载服务端返回405问题

Posted on 2016-11-18   |   In Android   |   visitors

最近遇到了一个问题,在项目中有一个启动页广告图片下载的功能,之前能够正常下载,由于这个版本遇到了运营商DNS劫持的问题,服务端要调整图片的下载路径,也就是改变了图片的链接地址。修改地址之后下载就出现异常了,经过断点调试发现http请求的返回码为405,查了一下405的意思。

405 Method Not Allowed(不允许使用的方法) 不支持该Request的方法。

那么我们就知道突破点了,只需要设置正确的请求方法就可以解决问题。原本的代码如下:

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
private void downloadImage(SplashBean splashBean) {
for (final SplashImage splashImage : splashBean.data.list) {
String name = URLUtil.guessFileName(splashImage.image, "Content-Disposition", null);
if (!TextUtils.isEmpty(splashImage.image)) {
InputStream is = null;
FileOutputStream fileOutputStream = null;
try {
URL url = new URL(splashImage.image);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(5000);
conn.setConnectTimeout(5000);
conn.setDoOutput(true);
if (HttpURLConnection.HTTP_OK != conn.getResponseCode()) {
Log2345.d(TAG, "连接异常---responseCode = " + conn.getResponseCode());
return;
}
is = conn.getInputStream();
File imageFile = new File(StorageUtils.getCacheDirectory(AllianceApplication.appContext), name);
fileOutputStream = new FileOutputStream(imageFile);
byte[] buffer = new byte[16 * 1024];
int read;
while ((read = is.read(buffer)) != -1) {
fileOutputStream.write(buffer, 0, read);
}
is.close();
fileOutputStream.close();
/**
* 对比文件MD5值
*/
String md5 = GetMD5.getMd5ByFile(imageFile);
Log2345.d(TAG, "MD5对比:" + md5 + "--" + splashImage.md5);
if (md5.equals(splashImage.md5)) {
files.add(imageFile);
}
if (files.size() == splashBean.data.list.size()) {
Log2345.d(TAG, "file.size = " + files.size());
SharedPreferencesUtils.setSplashVersion(splashBean.data.version);
}
SharedPreferencesUtils.setSplashInfo(JSON.toJSONString(splashBean));
} catch (Exception e) {
e.printStackTrace();
}
}
}
}

通过抓包发现发送出去的请求为 POST 请求,这点就有点奇怪了,HttpURLConnection 默认的请求方法应该是 GET 求,在这里我并没有设置请求方法为什么抓包看到的是 POST 请求呢?于是在 StackOverFlow 上找到了原因。

StackOverFlow

看字面的意思是说如果调用了 setDoOutput(true) 这个方法的话,默认的 GET 请求会改变为 POST 请求,因为 GET 请求是没有 request body 的。这就解释了之前为什么没有设置请求方法默认应该是 GET 请求,抓包缺看到的是 POST 请求了。那么只需要修改一下代码问题就解决了。

1
2
3
4
5
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");//设置请求方法为 GET 请求
conn.setUseCaches(false);
conn.setReadTimeout(5000);
conn.setConnectTimeout(5000);

如上代码,删除掉 setDoOutput(true) 这个方法即可。这个时候问题已经解决了,请求返回码为 200 ,图片下载成功~

Piccasso图片圆角及圆形图片实现

Posted on 2016-10-18   |   In Android   |   visitors

在开发中我们会经常遇到对图片进行圆角处理,以及现在流行的头像等将图片处理成圆形,Piccasso提供了transform这个机制,我们可以利用这个机制,在图片展示之前对图片进行处理,处理方式只需要实现
Transformation 接口即可,下面我们来看一下实现代码。

图片圆角

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
public class RoundedTransform implements Transformation {
private final int radius;
private final int margin;
public RoundedTransform(final int radius, final int margin) {
this.radius = radius;
this.margin = margin;
}
@Override
public Bitmap transform(Bitmap source) {
final Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setShader(new BitmapShader(source, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
Bitmap output = Bitmap.createBitmap(source.getWidth(), source.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
canvas.drawRoundRect(new RectF(margin, margin, source.getWidth() - margin, source.getHeight() - margin), radius, radius, paint);
if (source != output) {
source.recycle();
}
return output;
}
@Override
public String key() {
return "rounded(radius=" + radius + ", margin=" + margin + ")";
}
}

圆形图片

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
public class CircleTransform implements Transformation {
@Override
public Bitmap transform(Bitmap source) {
int size = Math.min(source.getWidth(), source.getHeight());
int x = (source.getWidth() - size) / 2;
int y = (source.getHeight() - size) / 2;
Bitmap squaredBitmap = Bitmap.createBitmap(source, x, y, size, size);
if (squaredBitmap != source) {
source.recycle();
}
Bitmap bitmap = Bitmap.createBitmap(size, size, source.getConfig());
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
BitmapShader shader = new BitmapShader(squaredBitmap, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP);
paint.setShader(shader);
paint.setAntiAlias(true);
float r = size / 2f;
canvas.drawCircle(r, r, r, paint);
squaredBitmap.recycle();
return bitmap;
}
@Override
public String key() {
return "circle";
}
}

Gradle基础及常用命令

Posted on 2016-10-13   |   In Gradle   |   visitors

什么是Gradle

现在大部分的Android开发者所用的 IDE 应该都是 AndroidStudio 了,我们知道 AS 中的项目是基于 Gradle 构建的。Gradle 是一种基于 Groovy 语言的构建工具,Groovy 语法跟 Java 语法很相像,是一种动态语言,而且在 Java 基础上做了不少改进,用起来更加简洁、灵活。

Gradle Wrapper

现在默认新建一个项目,然后点击 AS 上运行,默认就会直接帮你安装 Gradle ,我们不需要额外的安装 Gradle 了,但是其实这个 Gradle 不是真正的 Gradle ,他叫 Gradle Wrapper ,意为 Gradle 的包装,什么意思呢?假设我们本地有多个项目,一个是比较老的项目,还用着 Gradle 1.0 的版本,一个是比较新的项目用了 Gradle 2.0 的版本,但是你两个项目肯定都想要同时运行的,如果你只装了 Gradle 1.0 的话那肯定不行,所以为了解决这个问题,Google 推出了 Gradle Wrapper 的概念,就是他在你每个项目都配置了一个指定版本的 Gradle ,你可以理解为每个 Android 项目本地都有一个小型的 Gradle ,通过这个每个项目你可以支持用不同的 Gradle 版本来构建项目。

Gradle常用命令

  • 查看构建版本 ./gradlew -v
  • 清除build文件夹 ./gradlew clean
  • 检查依赖并编译打包 ./gradlew build (会把debug和release包都打出来)
  • 编译并打Debug包 ./gradlew assembleDebug
  • 编译并打release包 ./gradlew assembleRelease
  • Release模式打包并安装 ./gradlew installRelease
  • 卸载Release模式包 ./gradlew uninstallRelease

assemble还可以结合productFlavor实现多渠道打包

注:./ 代表当前目录,gradlew 意为 Gradle Wrapper

参考文献

GRADLE基础

Gradle 常用命令参数及解释

三星手机拍照图片自动旋解决方法

Posted on 2016-10-12   |   In Android   |   visitors

最近项目中遇到一个手机拍照的问题,就是三星、索尼等厂家的手机拍摄的照片呈现在ImageView上的时候图片会自动的旋转,由于项目中有发帖功能,这样用户在上传图片的时图片的角度就不正确了。在搜索了一些资料之后,找到了解决办法,思路很简单:

  1. 获取图片旋转的角度
  2. 在显示图片时使图片旋转回正确的角度

我们来看一下实现代码

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
/**
* 读取图片的旋转的角度
* @param path 图片绝对路径
* @return 图片的旋转角度
*/
public static int getBitmapDegree(String path) {
int degree = 0;
try {
// 从指定路径下读取图片,并获取其EXIF信息
ExifInterface exifInterface = new ExifInterface(path);
// 获取图片的旋转信息
int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
degree = 90;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
degree = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
degree = 270;
break;
}
} catch (IOException e) {
e.printStackTrace();
}
return degree;
}

代码很容易理解,注释写很清楚,在设置显示图片时根据获取的旋转角度将图片旋转回去即可,这样问题就解决了,enjoy 😁

12
lihongxiangleo

lihongxiangleo

AndroidDeveloper Popping Dancer

6 posts
3 categories
4 tags
GitHub 微博 豆瓣
Creative Commons
© 2016 - 2017 lihongxiangleo
Powered by Hexo
Theme - NexT.Pisces