Android 绘制圆形图片

记录一下,以免忘记,以备使用。

方法一:

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
public class MyView extends View {

Paint paint = new Paint();
Shader shader;
Matrix mat = new Matrix();
Bitmap bitmap;

public MyView(Context context) {
this(context, null);
}

public MyView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}

public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);

// create a bitmap from the image resource what we want to draw
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.dossier_icon);
// a bitmap shader, would be set into paint, here we use repeat tile mode, but since we'll
// scale to make the bitmap fill the canvas just right, so there would be no repeat.
shader = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
// after this, the paint would contains this bitmap.
paint.setShader(shader);
}

@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
// scale to make bitmap fill the canvas
mat.setScale((float)getWidth() / bitmap.getWidth(), (float)getHeight() / bitmap.getHeight());
shader.setLocalMatrix(mat);
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// draw a circle with the paint.
canvas.drawCircle(getWidth() / 2, getHeight() / 2, getWidth() / 2, paint);
}
}

Read More

给三星 tablet SM-T830 刷机[续]

事情的起因是,从 xda 上面这个帖子 看到,有人在三星 Tab S4 平板上面刷了个类原生 Android 的系统,他表示用起来挺好,只不过 4 个扬声器只有底部两个可以发声。看到这个我心里就痒痒,因为三星的官方 rom 我并不喜欢,里面有三星的 app store,还有三星的一套账户系统,调试到系统代码的时候,行号也完全对不上(Pixel是可以对上行号的),所以我也想给手里的 Tab S4 平板刷一个类原生系统。

Read More

Android Toast 两个 Crash

Toast 是 Android 系统一种非常简单的提示性小工具,最近我尝试修复 Toast 相关的两种 Crash,所以把相关的原委和过程记录了下来。先来看一下第一种 Crash 的 log:

1
2
3
4
5
6
7
8
9
10
android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy@e2815e is not valid; is your activity running?
at android.view.ViewRootImpl.setView(ViewRootImpl.java:679)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:342)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:93)
at android.widget.Toast$TN.handleShow(Toast.java:459)
at android.widget.Toast$TN$2.handleMessage(Toast.java:342)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6119)
at java.lang.reflect.Method.invoke(Native Method)

Read More

Java Comparable Contracts

实现 Java 中的 Comparable 接口的对象,可以用在 Collections#sort 等方法中进行排序等。通常来说,Comparable 接口的 compareTo 方法都是写起来比较简单的。不过,偶尔还是可能翻车的。比如下面的 crash log,就是翻车的现场:

1
2
3
4
5
6
7
8
java.lang.IllegalArgumentException: Comparison method violates its general contract! 
at java.util.TimSort.mergeHi(TimSort.java:868)
at java.util.TimSort.mergeAt(TimSort.java:485)
at java.util.TimSort.mergeCollapse(TimSort.java:408)
at java.util.TimSort.sort(TimSort.java:214)
at java.util.TimSort.sort(TimSort.java:173)
at java.util.Arrays.sort(Arrays.java:659)
at java.util.Collections.sort(Collections.java:217)

Read More

矩阵运算在 Android 中的简单场景

让我们先从位于 android.graphics 包中的 Bitmap 类的一个方法开始说起,也就是 createBitmap(Bitmap source, int x, int y, int width, int height, Matrix m, boolean filter) 这样一个方法。这个方法中有个矩阵参数,通过传入此矩阵参数,可以将 source Bitmap 经过一定的转换再创建目标 Bitmap。那么这个矩阵是怎么起作用的呢?先看一段示例代码:

Read More

微信 Android 版是如何计步的

很早以前,我使用一部 iPhone 5S 手机,这是第一款带有计步功能的 iPhone 机型,苹果称之为搭载运动协处理器。如果我没记错,iOS 的运动数据,既可以被第三方 app 读取,也可以被写入。读取好说,写入是因为用户可能使用手环之类的东西来记录数据,那么这些数据可能比 iOS 系统中的数据更受用户重视,所以就可以把 iOS 系统中的数据替换为手环产生的数据,所以需要允许写入。不过目前而言,Android 系统中,第三方应用似乎无法写入系统的运动数据,而只能读取。

Read More

不一样的 RelativeLayout measure 过程

直接用一个简单的例子展示 RelativeLayout 的不一样之处:

图中,左边是一个简单的 Android layout 例子,例子中在外侧是一个最大的 horizontal 的 LinearLayout,它有 3 个 child,分别是左部、分割线和右部。左部和右部非常相似,都是外面一个 ViewGroup 内嵌一个 TextView,且 ViewGroup 的高度都是 wrapContent 而内嵌的 TextView 的高度都是 matchParent.

Read More

一键设置 Android http proxy 的尝试

自打来到杭州后,调试 Android app 时用 Charles 做代理的场景成了非常常见的操作,而让人烦恼的是,每次都需要进入手机的 WiFi -> 点击当前 WiFi -> 点击编辑 -> 点击 Advanced options -> proxy 选择 None 或者 Manual -> 上一步如果选了 Manual, 则需要输入 IP 地址和端口号 -> 保存。

Read More

ShadowSocks for Gradle & Shell

ShadowSocks 是个很好的工具,它自带 PAC 模式和全局模式。

不过这个全局模式并不能完全让整台电脑的所有网络访问全部通过代理进行,比如终端命令就不可以。我打开全局代理后,然后在终端执行 curl ip.cn 命令,结果显示检查到的 IP 地址依然是本机真实的公网 IP:

Read More

Don't let Your App Drain your Users' Battery

What drives battery Life?

    Read More