TryCatch Blog


  • 首页

  • 归档

  • 分类

  • 标签

  • 搜索
close
TryCatch Blog

Charles的安装和使用

发表于 2017-07-18 | | 阅读次数
下载安装Charles

这里提供下载安装地址

http://charlesproxy.iiilab.com/4_1_4/charles.jar

破解文件

https://raw.githubusercontent.com/guoyoujin/guoyoujin.github.io/develop/download/charles.jar

帮助地址

http://charles.iiilab.com/

安装之后打开Charles即可

破解Charles

找到应用程序里面的Charles ===>>右击鼠标====>>显示包内容===>>进入文件夹/Contents/Java里面,之后把破解文件charles.jar替换掉即可,如下图所示
png

png

安装证书

选择Help里面的

png

png

png

手机安装证书

在Safari浏览器里面输入网址 :chls.pro/ssl按照提示进行操作

TryCatch Blog

android px sp dp解密

发表于 2017-05-17 | 分类于 android | | 阅读次数

分辨率:屏幕上显示的像素个数,单位尺寸内像素点越多,显示的图像就越清楚

1
2
3
4
5
主流分辨率:480*800、720*1280、1080*1920
像素密度
240dpi(480*800)、320dpi(720*1280)、480dpi(1080*1920)
单位
px:像素

dp:设备独立像素(160dpi为标准)

1
2
3
240dpi下,1dp=1.5px
320dpi下,1dp=2px
480dpi下,1dp=3px

sp:等同于dp,用于描述字体大小

1
2
3
240dpi下,1sp=1.5px
320dpi下,1sp=2px
480dpi下,1sp=3px

常见分辨率

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
4:3
VGA 640*480
QVGA 320*240
HVGA 480*320
SVGA 800*600
5:3
WVGA 800*480
16:9
FWVGA 854*480
HD 1920*1080
QHD 960*540
720p 1280*720
1080p 1920*1080
Apple
iPhone4/4s 960*640
iPhone5/5s 1136*640
iPhone6 1334*750
iPhone6Plus 1920*1080
小米1 854*480
小米2 1280*720
红米1/1s/note 1280*720
对应的DPI
HVGA mdpi
WVGA hdpi
FWVGA hdpi
QHD hdpi
720p xhdpi
1080p xxhdpi

最佳方案

1
2
3
4
选取320dpi下(720*1280)进行设计,此分辨率下1dp=2px
对于一切切图资源特殊处理
输出多套分辨率的切图,例如480p和720p,在设计的时候要注意好切图区域的大小能被2和1.5整除的大小,如48p*48px、96*96px等。
使用相对于单位进行标注

采用自适应布局
标注尽量采用相对关系

文字

1
2
3
中文字体:默认为Droid Sans Fallback,设计时可采用微软雅黑。
英文字体:Andriod4.x及以上采用Roboto,Andrio2.x和andriod3.x采用 Droid Sans。建议尽量采用系统默认字体。
Andriod规范建议,字号采用12sp、14sp、18sp、22sp等四个级别来设计。(实际设计时可以按实际情况调整)

总结

1
2
3
4
5
采用720*1280分辨率来进行设计。(设计时,采用偶数值进行设计,方便dp和px的转换)
开始标注了,标注尽量采用相对位置进行标注。
切图了,在720*1280下进行切图,可以完全适配720*1280后放大缩小切图资源
分别适配480*800、1080*1920
不要忘记了,开发完后要进行bug测试(视觉方面的)
TryCatch Blog

Android 6.0权限一刀切问题

发表于 2017-05-17 | 分类于 android | | 阅读次数

今天使用m4的时候突然发现程序抛出异常了,原因是因为升级了小米的最新系统MIUI7.3稳定版本,仔细一看发现是Android6.0.1的操作系统,瞬间想到Android6.0的Requesting Permissions at Run Time特性。于是找到了google的官方文档和demo进行脑补

官方文档:
https://developer.android.com/training/permissions/requesting.html/

官方demo:

https://github.com/googlesamples/android-RuntimePermissions/blob/master/Application/src/main/java/com/example/android/system/runtimepermissions/MainActivity.java/

首先必须在AndroidManifest.xml文件里面声明需要用到的权限,下面是一个权限例子

1
<uses-permission android:name="android.permission.READ_PHONE_STATE" />

至于代码实现如下:

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
int REQUEST_READ_PHONE=101;
public void initPermission(){
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_PHONE_STATE)) {
// Show an expanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_PHONE_STATE},
REQUEST_READ_PHONE);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == REQUEST_READ_PHONE){
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//PERMISSION GRANTED
} else {
//PERMISSION DENIED permission denied
Toast.makeText(this, "您拒绝了权限请求,应用程序无法正常工作,请手动设置权限为允许", Toast.LENGTH_LONG).show();
}
} else {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
TryCatch Blog

fragment onAttach(Context context) and onAttach(Activity activity)

发表于 2017-05-17 | 分类于 android | | 阅读次数

在使用dagger2为了解决依赖关系注入fragment的时候,发现我在注入Presenter的时候老是报空指针异常,郁闷了两天没解决这个问题,代码如下

抽象framgent

1
2
3
4
5
6
7
8
9
10
public abstract class BaseFragment extends Fragment {
private static final String TAG = "BaseFragment";
@Override
public void onAttach(Context context) {
super.onAttach(context);
setupComponent((TxAssistantComponent) TxAssistantApplication.get(context).component());
}
protected abstract void setupComponent(TxAssistantComponent appComponent);
}

在需要的fragment里面注入

1
2
3
4
5
6
7
8
9
@Inject
OrderListFragmentPresenter orderListFragmentPresenter;
@Override
protected void setupComponent(TxAssistantComponent appComponent) {
DaggerOrderListFragmentComponent.builder().txAssistantComponent(appComponent)
.orderListFragmentModule(new OrderListFragmentModule())
.build().inject(this);
}

这个写法在android5.0以上是没问题的,后来回到家写代码的时候用了一个android4.4的手机,就出现上面所说的错误,这就把我郁闷的了,搞了一晚上没搞定,总感觉代码写的没错,由于对dagger2没啥了解,我就以为是dagger2的注入可能出了问题,于是就各种搜索,最后只能先睡觉了。

今天在公司发现用android5.0的手机就是运行流畅,脑子灵光一闪,会不会是生命周期的问题,果断serch了一下,还真是这个问题,导致这个根本的问题就是国内的android系统被深度定制引起的,后面找到解决办法,只需在全局抽象fragment添加如下方法即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public abstract class BaseFragment extends Fragment {
private static final String TAG = "BaseFragment";
@Override
public void onAttach(Context context) {
super.onAttach(context);
setupComponent((TxAssistantComponent) TxAssistantApplication.get(context).component());
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
setupComponent((TxAssistantComponent) TxAssistantApplication.get(activity).component());
}
protected abstract void setupComponent(TxAssistantComponent appComponent);
}

TryCatch Blog

ng-file-upload使用

发表于 2017-05-17 | 分类于 js | | 阅读次数

github地址

1.引入js文件

1
2
//= require adminAngular/lib/ng-file-upload-shim.min
//= require adminAngular/lib/ng-file-upload.min

2.注入

1
var controllers = angular.module('controllers', ['services', 'directives','ngFileUpload','xeditable']);

3.注入controller

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
controllers.controller('ProductGroupManagementCtrl',['$scope', '$uibModal', 'mallOrderHttp', 'get_params','$uibModalInstance', '$state','Upload',function($scope,$uibModal,mallOrderHttp,get_params,$uibModalInstance,$state,Upload){
$scope.upload = function (files,product_group_id) {
if (files && files.length) {
for (var i = 0; i < files.length; i++) {
var file = files[i];
Upload.upload({
url: '/api/admin/v1/mall_orders/update_product_group',
data: { 'id': product_group_id },
file: file
}).progress(function (evt) {
//进度条
var progressPercentage = parseInt(100.0 * evt.loaded / evt.total);
console.log('progess:' + progressPercentage + '%' + evt.config.file.name);
}).success(function (data, status, headers, config) {
//上传成功
console.log('file ' + config.file.name + 'uploaded. Response: ' + data);
$scope.uploadImg = data;
$scope.select_list_change();
}).error(function (data, status, headers, config) {
//上传失败
console.log('error status: ' + status);
});
}
}
};
//查看大图
$scope.show_big_image = function(objValue){
$(this).ekkoLightbox({
remote:objValue.image.url
});
}
}]);

4.html文件

1
2
3
4
5
6
7
8
9
10
<td>
<a href="javascript:void();" ng-click="show_big_image(product_group)">
<img style="display: inline-block;width:30px;height:30px" ng-src="{{product_group.image.url}}" />
</a>
<span class="btn btn-success fileinput-button btn-xs">
<i class="glyphicon glyphicon-plus"></i>
<span>文件上传</span>
<input ngf-select ngf-change="upload($files,product_group.id)" ngf-multiple="true" type="file"/>
</span>
</td>
TryCatch Blog

上传android lib到jcenter库上面碰到的一些问题,以及解决办法

发表于 2017-05-17 | | 阅读次数

1.账号首先你得要有jcenter的账号,最简单的就是用google登陆了

请移步

2.接下来就是拿到你自己的appk 和appid了,

拿到这些东西之后,放到根目录下的local.properties文件里面,具体内容如下:

1
2
3
4
5
## This file is automatically generated by Android Studio.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
sdk.dir=/Users/guoyoujin/Library/Android/sdk
bintray.user=trycatch
bintray.apikey=12345

3.接下来就是引入需要的插件了,这里我采用了最新的gradle配置,配置如下:

(1)根目录build.gradle配置

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
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.1.0'
classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.4'
classpath 'com.github.dcendents:android-maven-gradle-plugin:1.4.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
mavenCentral()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}

(2)lib 的build.gradle配置

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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
apply plugin: 'com.android.library'
apply plugin: 'com.github.dcendents.android-maven'
apply plugin: 'com.jfrog.bintray'
android {
compileSdkVersion 23
buildToolsVersion "23.0.3"
resourcePrefix "bounceprogressbar__" //这个随便填
defaultConfig {
minSdkVersion 14
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.4.0'
compile 'com.nineoldandroids:library:2.4.0+'
}
// 这个version是区分library版本的,因此当我们需要更新library时记得修改这个version
// 这个version影响后面的引用
version = "1.0.0"
def siteUrl = 'https://github.com/guoyoujin/MySnackBar' // 项目的主页
def gitUrl = 'https://github.com/guoyoujin/MySnackBar.git' // Git仓库的url
group = "com.trycatch.android" // Maven Group ID for the artifact,一般填你唯一的包名
install {
repositories.mavenInstaller {
// This generates POM.xml with proper parameters
pom {
project {
packaging 'aar'
// Add your description here
name 'Android SnackBar Widget' //项目描述
url siteUrl
// Set your license
licenses {
license {
name 'The Apache Software License, Version 2.0'
url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
}
}
developers {
developer {
id 'guoyoujin' //填写的一些基本信息
name 'TryCatch'
email 'guoyoujin123@gmail.com'
}
}
scm {
connection gitUrl
developerConnection gitUrl
url siteUrl
}
}
}
}
}
task sourcesJar(type: Jar) {
from android.sourceSets.main.java.srcDirs
classifier = 'sources'
}
task javadoc(type: Javadoc) {
source = android.sourceSets.main.java.srcDirs
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
}
task javadocJar(type: Jar, dependsOn: javadoc) {
classifier = 'javadoc'
from javadoc.destinationDir
}
artifacts {
archives javadocJar
archives sourcesJar
}
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
bintray {
user = properties.getProperty("bintray.user")
key = properties.getProperty("bintray.apikey")
configurations = ['archives']
pkg {
repo = "maven"
name = "MySnackBar" //发布到JCenter上的项目名字
websiteUrl = siteUrl
vcsUrl = gitUrl
licenses = ["Apache-2.0"]
publish = true
}
}

(3)配置gradle的版本:在文件gradle/wrapper/gradle-wrapper.properties

1
2
3
4
5
6
#Mon Dec 28 10:00:20 PST 2015
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip

(4)查看你的gradle版本,输入命令

1
2
3
4
5
6
7
8
9
10
11
12
13
➜ MyCustomSnackBar git:(master) ✗ gradle -v
------------------------------------------------------------
Gradle 2.14.1
------------------------------------------------------------
Build time: 2016-07-18 06:38:37 UTC
Revision: d9e2113d9fb05a5caabba61798bdb8dfdca83719
Groovy: 2.4.4
Ant: Apache Ant(TM) version 1.9.6 compiled on June 29 2015
JVM: 1.8.0_40 (Oracle Corporation 25.40-b25)
OS: Mac OS X 10.11.6 x86_64

可以看到我的gradle版本是最新的gradle 2.14.1
而且我是用home brew管理的gradle,你也可以使用这个插件管理,他是用ruby写的

4.环境配置好了接下来就是输入命令了

1
2
3
gradle install or sudo gradle install
gradle bintrayUpload or sudo gradle bintrayUpload

如果中间没有什么问题的话,那就应该是返回success了

5.接下来就是在jcenter里面点击 AddToJcenter发出一个请求等着就行了

6.AddToJcenter成功之后,最后就是引用自己的lib库了,代码如下:

1
2
3
dependencies {
compile 'com.trycatch.android:mysnackbar:1.0.0'
}
TryCatch Blog

关于ruby赋值的一些注意事项

发表于 2017-05-17 | 分类于 ruby | | 阅读次数

看下面代码:

1
2
3
4
5
6
7
8
9
10
params = {a:"1",b:"2",c:"3"}
=> {:a=>"1", :b=>"2", :c=>"3"}
pa = params
=> {:a=>"1", :b=>"2", :c=>"3"}
pa.delete(:a)
=> "1"
params
=> {:b=>"2", :c=>"3"}
pa
=> {:b=>"2", :c=>"3"}

发现了吗?我执行

1
2
3
4
5
6
7
8
9
10
11
```ruby
params = {a:"1",b:"2",c:"3"}
=> {:a=>"1", :b=>"2", :c=>"3"}
pa = params.clone
=> {:a=>"1", :b=>"2", :c=>"3"}
pa.delete(:a)
=> "1"
pa
=> {:b=>"2", :c=>"3"}
params
=> {:a=>"1", :b=>"2", :c=>"3"}

对没错就是上面的clone方法。当然你也可以使用ruby的深拷贝

让我们在看下方法里面传参数的使用

1
2
3
4
5
6
7
8
9
10
params = {a:"1",b:"2",c:"3"}
=> {:a=>"1", :b=>"2", :c=>"3"}
def format_params pa=nil
pa.delete(:a)
end
=> :format_params
format_params(params)
=> "1"
params
=> {:b=>"2", :c=>"3"}

我擦哦,方法穿参数居然也是这么坑,有木有,所以大家自己注意点
再来看数组

1
2
3
4
5
6
7
8
9
10
params = [1,2,3,4,5]
=> [1, 2, 3, 4, 5]
def format_params pa=nil
pa[0]=100
end
=> :format_params
format_params(params)
=> 100
params
=> [100, 2, 3, 4, 5]

数组也会这样啊,醉了

不过大家别害怕,这些问题只是存在于一些hash ,json,array数据才会出现的,下面看代码

1
2
3
4
5
6
7
8
9
10
a = 100
=> 100
def format_a p=nil
p = 200
end
=> :format_a
format_a(a)
=> 200
2.2.5 :042 > a
=> 100

这个还好不会变哈

TryCatch Blog

关于http和https允许请求设置header问题

发表于 2017-05-17 | 分类于 https | | 阅读次数

在给微信小程序提供接口的时候使用的是

1
不过服务器一直没获取到,怀疑可能是```nginx```没有允许设置```header```。解决办法就是在```nginx```配置文件里面加上```underscores_in_headers on

在给微信小程序提供接口的时候使用的是https,token是放在header里面,
不过服务器一直没获取到,怀疑可能是nginx没有允许设置header。解决办法就是在nginx配置文件里面加上underscores_in_headers on;

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
### wechatapi Start
upstream wechatapi {
server localhost:8009;
}
server {
listen 443 ssl;
server_name api.test.org;
underscores_in_headers on;
ssl on;
ssl_certificate /ssl/bundle.crt;
ssl_certificate_key /ssl/txzs_unsecure.key;
client_max_body_size 20M;
access_log /system/logs/wechatapi_access.log;
error_log /system/logs/wechatapi_error.log;
root /system/wechatapi/current/public;
index index.html;
location / {
try_files $uri @wechatapi;
}
location @wechatapi {
proxy_read_timeout 300;
proxy_connect_timeout 300;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://wechatapi;
}
error_page 403 /500.html;
error_page 404 /500.html;
error_page 405 /500.html;
error_page 500 501 502 503 504 /500.html;
location ^~ /error/ {
internal;
root /system/wechatapi/current/public;
}
location /images/ {
try_files $uri /images/error.jpg;
}
}
# wechatapi end

TryCatch Blog

ruby 关于返回几秒前,几小时前,1天前......

发表于 2017-05-17 | 分类于 ruby | | 阅读次数

这个需求是:
当小于60秒的时候返回时间为xx秒前;
当小于60分钟大于60秒的时候返回xxx小时前;
当隔1天的时候显示一天前;
当大于隔2天的时候,显示xx月xx日;
当跨年的时候显示xxxx年xx月xx日;

下面是实现代码,具体的话你可以按照你的需求进行修改

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
module TimeFormat
def self.time_text new_time=Time.now,old_time=Time.now
if new_time.year == old_time.year
hour_subtract = new_time.to_i/3600 - old_time.to_i/3600
min_subtract = new_time.to_i/60 - old_time.to_i/60
sec_subtract = new_time.to_i - old_time.to_i
if new_time.at_beginning_of_day == old_time.at_beginning_of_day
if min_subtract<60
if sec_subtract<60
"#{sec_subtract}秒前"
else
"#{min_subtract}分钟前"
end
else
"#{hour_subtract}小时前"
end
else
if (old_time.at_beginning_of_day+1.day) == new_time.at_beginning_of_day
"1天前"
else
old_time.strftime("%m月%d日")
end
end
else
old_time.strftime("%Y年%m月%d日")
end
end
end

TryCatch Blog

使用微信的 JS SDK 选取手机照片并进行上传,Iphone无法显示缩略图

发表于 2017-05-17 | 分类于 js | | 阅读次数

前言

最近从三月初开始就发现有用户反应微信浏览器选择图片显示不了预览,仔细查找发现跟微信最近升级浏览器内核有关,发现需要升级weixin js sdk了,并且需要修改一些方法,以及对一些老版本的兼容。

weixin选取图片代码(老版本jweixin-1.2.0.js之前的版本)

1
2
3
4
5
6
7
8
9
wx.chooseImage({
count: 1,
sizeType: ['original', 'compressed'],
sourceType: ['album', 'camera'],
success: function (res) {
var localId = res.localIds[0];
$('img.avatar-temp').attr('src', localId);
}
)};

使用如上代码发现图片在iphone上无法显示,Android上可以无差别显示,那肯定是浏览器内核的问题了,解决办法就是升级weixin js sdk喽,直接升级微信js sdk

1
<script src="https://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>

接下来就是修改选显示图片的步骤了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
wx.chooseImage({
count: 1,
sizeType: ['original', 'compressed'],
sourceType: ['album', 'camera'],
success: function (res) {
var localId = res.localIds[0];
if(window.__wxjs_is_wkwebview){
wx.getLocalImgData({
localId: auth_image.localId,
success: function (res) {
var localData = res.localData;
localData = localData.replace('jgp', 'jpeg');
$('img.avatar-temp').attr('src', localData);
},
fail:function(res){
alert(res.errMsg);
}
});
}else{
$('img.avatar-temp').attr('src', localId);
}
}
)};

使用getLocalImgData方法即可在wkwebview浏览器内核也可以正常显示图片了。注意记得一定要判断浏览器内核,不然总有一个出问题的,并且在else里面做你该做的事情,千万别忘了!!!!

weixin上传图片

我选择直接上传到微信服务器上面,然后在利用反回的图片地址,让自己服务器去异步下载图片

1
2
3
4
5
6
7
8
9
10
wx.uploadImage({
localId: localId,
isShowProgressTips: 1,
success: function (res) {
auth_image.serverId = res.serverId;
},
fail: function (res) {
alert(JSON.stringify(res));
}
});

12
TryCatch

TryCatch

千里之行,始于足下

12 日志
6 分类
10 标签
GitHub Twitter 微博 豆瓣
© 2017 TryCatch
由 Hexo 强力驱动
主题 - NexT.Pisces