咸鱼

咸鱼是以盐腌渍后,晒干的鱼

0%

1. 运行时找不到so文件

具体表现为:已经在libs目录添加了所有平台的so文件,但是运行是依然提示找不到so文件。

如:

1
2
java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.example.ijkplayer-CyD2mFQ8g6fyehi-g_1ALQ==/base.apk"],nativeLibraryDirectories=[/data/app/com.example.ijkplayer-CyD2mFQ8g6fyehi-g_1ALQ==/lib/arm64, /system/lib64, /vendor/lib64]]] couldn't find "libijkffmpeg.so"
at java.lang.Runtime.loadLibrary0(Runtime.java:1012)

问题:
编译时,jniLibs默认的路径是 /app/src/main/jniLibs ,如果so文件放在 /app/libs 需指定目录。

阅读全文 »

拷贝以下的内容(https://developer.android.com/studio/build/shrink-code.html
),以防平时不能访问 ,有条件的可以访问原文,排版更好,看得舒服。

压缩代码和资源

要尽可能减小 APK 文件,您应该启用压缩来移除发布构建中未使用的代码和资源。此页面介绍如何执行该操作,以及如何指定要在构建时保留或舍弃的代码和资源。
代码压缩通过 ProGuard 提供,ProGuard 会检测和移除封装应用中未使用的类、字段、方法和属性,包括自带代码库中的未使用项(这使其成为以变通方式解决 64k 引用限制的有用工具)。ProGuard 还可优化字节码,移除未使用的代码指令,以及用短名称混淆其余的类、字段和方法。混淆过的代码可令您的 APK 难以被逆向工程,这在应用使用许可验证等安全敏感性功能时特别有用。
资源压缩通过适用于 Gradle 的 Android 插件提供,该插件会移除封装应用中未使用的资源,包括代码库中未使用的资源。它可与代码压缩发挥协同效应,使得在移除未使用的代码后,任何不再被引用的资源也能安全地移除。
本文介绍的功能依赖下列组件:
SDK Tools 25.0.10 或更高版本
适用于 Gradle 的 Android 插件 2.0.0 或更高版本

压缩代码

要通过 ProGuard 启用代码压缩,请在 build.gradle
 文件内相应的构建类型中添加 minifyEnabled true

请注意,代码压缩会拖慢构建速度,因此您应该尽可能避免在调试构建中使用。不过,重要的是您一定要为用于测试的最终 APK 启用代码压缩,因为如果您不能充分地自定义要保留的代码,可能会引入错误。
例如,下面这段来自 build.gradle
 文件的代码用于为发布构建启用代码压缩:
android { buildTypes { release { minifyEnabled true proguardFiles getDefaultProguardFile(‘proguard-android.txt’), ‘proguard-rules.pro’ } } …}
:Android Studio 会在使用 Instant Run 时停用 ProGuard。如果您需要为增量式构建压缩代码,请尝试试用 Gradle 压缩器
除了 minifyEnabled
 属性外,还有用于定义 ProGuard 规则的 proguardFiles
 属性:
getDefaultProguardFile(‘proguard-android.txt’)
 方法可从 Android SDK tools/proguard/
 文件夹获取默认的 ProGuard 设置。提示:要想做进一步的代码压缩,请尝试使用位于同一位置的 proguard-android-optimize.txt
 文件。它包括相同的 ProGuard 规则,但还包括其他在字节码一级(方法内和方法间)执行分析的优化,以进一步减小 APK 大小和帮助提高其运行速度。

阅读全文 »

Java8

Java8上的自带Base64工具 java.util.Base64;

1
2
3
4
5
6
//编码
Base64.getEncoder().encodeToString("Hello".getBytes("utf-8"));

//解码
byte[] asBytes = Base64.getDecoder().decode("SGVsbG8=");
System.out.println(new String(asBytes, "utf-8"));

Android

Android SDK 自带 android.util.Base64;

阅读全文 »

由于不太想用Eclipse的库,寻求其他库来试试。

org.fusesource.mqtt-client 也是MQTT推荐 client 端的库,github的start也有500+吧,fork也有200+

引用库

1
compile 'org.fusesource.mqtt-client:mqtt-client:1.12'

作者给出了三种使用方法:1.阻塞;2.非阻塞(推荐);3.Future(没理解?)

阅读全文 »

apktool是apk反编译的核心,其他GUI工具内部都是用apktool来执行反编译任务。

主页和下载地址

主页地址: https://ibotpeaches.github.io/Apktool/install/
下载apktool.jar: https://bitbucket.org/iBotPeaches/apktool/downloads/
下载apktool.bat:https://raw.githubusercontent.com/iBotPeaches/Apktool/master/scripts/windows/apktool.bat

apktool.bat内容如下:

1
2
3
4
5
@echo off
if "%PATH_BASE%" == "" set PATH_BASE=%PATH%
set PATH=%CD%;%PATH_BASE%;
chcp 65001 2>nul >nul
java -jar -Duser.language=en -Dfile.encoding=UTF8 "%~dp0\apktool.jar" %*
阅读全文 »

Android机子刷机,遇到个频率(几秒一次)弹广告的内置流氓软件,作为service运行,可以进程保活,也就是强行关闭进程,它可以重新启动,非常恶心,时不时就来一个全屏广告,自动下载其他的apk安装包,自动安装。电脑管家是识别为木马的。
看了一下他的 AndroidManifest.xml

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
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.xym.ma" platformBuildVersionCode="19" platformBuildVersionName="4.4.2-1456859">
<application android:icon="@drawable/ic_launcher" android:label="xym" android:name="com.xym.ma.a">
<activity android:exported="true" android:name="com.xym.ma.b" android:screenOrientation="portrait" android:theme="@android:style/Theme.Translucent"/>
<meta-data android:name="googlepotatooid" android:value="712c9cef25b42dc4"/>
<meta-data android:name="googlepotatoo_channel" android:value="ch0117"/>
<meta-data android:name="googlepotatoo_jd" android:value="true"/>
<activity android:name="com.zuhn.mkn.d.a" android:screenOrientation="portrait" android:theme="@android:style/Theme.Translucent.NoTitleBar">
<intent-filter>
<action android:name="com.zuhn.mkn.activity"/>
</intent-filter>
</activity>
<service android:exported="true" android:name="com.zuhn.mkn.b.a"/>
<receiver android:name="com.zuhn.mkn.a.b">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
<action android:name="android.intent.action.USER_PRESENT"/>
<action android:name="com.zuhn.mkn.destory"/>
</intent-filter>
</receiver>
<activity android:label="JDBrowserActivity" android:name="com.jd.jdadsdk.JDAdBrowser" android:screenOrientation="portrait" android:theme="@android:style/Theme.Translucent.NoTitleBar"/>
<service android:exported="false" android:name="com.qq.e.comm.DownloadService"/>
<activity android:configChanges="keyboard|keyboardHidden|orientation|screenSize" android:name="com.qq.e.ads.ADActivity"/>
</application>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="com.android.launcher.permission.UNINSTALL_SHORTCUT"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"/>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.GET_TASKS"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_CALL_LOG"/>
<uses-permission android:name="android.permission.READ_SMS"/>
</manifest>

http://square.github.io/retrofit/

准备

引入
1
2
compile 'com.squareup.retrofit2:retrofit:2.0.0'
compile 'com.squareup.retrofit2:converter-gson:2.+'

权限
1
<uses-permission android:name="android.permission.INTERNET" />

协议
1
2
/api/v1/user/login/{name}/{passwd}


Curl
1
curl -X GET --header 'Accept: application/json' 'http://192.168.1.219/api/v1/user/login/sam/123'

开始写代码

写一个API接口

阅读全文 »

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
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class Test {

public static void main(String[] args) throws IOException {

//cat /proc/meminfo

String commands="cat /proc/meminfo";

//String message= runCommands(commands);
//System.out.println(message);

getDiskInfo(1);
}

public static String runCommands(String commands) throws IOException{

Process process = Runtime.getRuntime().exec(commands);
InputStreamReader ir = new InputStreamReader(process.getInputStream(), "UTF-8");
BufferedReader input = new BufferedReader(ir);
String line;
String message="";
while ((line = input.readLine()) != null) {
//System.out.println("+++"+line);
message = message + line + "\n" ;
}
return message;
}

public static List<List> getDiskInfo(int sda_number) throws IOException{
String commands = "df -h |grep /dev/sda"+sda_number;
// String commands = "df -h";

Process process = Runtime.getRuntime().exec(commands);
InputStreamReader ir = new InputStreamReader(process.getInputStream(), "UTF-8");
BufferedReader input = new BufferedReader(ir);
String line;

List<List> result = new ArrayList();
/**
* [文件系统, 容量, 已用, 可用, 已用%, 挂载点]
* [/dev/sda1, 8.3G, 6.4G, 1.5G, 82%, /]
*/
while ((line = input.readLine()) != null) {
//System.out.println("----------"+line);
String[] temp = line.split(" ");
List<String> list_dev_sda = new ArrayList();
for (String string : temp) {
string = string.replaceAll(" ", "");
if(!string.equals("")){
//System.out.println(string);
list_dev_sda.add(string);
}
}
System.out.println(list_dev_sda.toString());
result.add(list_dev_sda);
}
return result;
}

public static HashMap<String, Float> getMemInfo() throws IOException{

String commands = "cat /proc/meminfo";
Process process = Runtime.getRuntime().exec(commands);
InputStreamReader ir = new InputStreamReader(process.getInputStream(), "UTF-8");
BufferedReader input = new BufferedReader(ir);
//读第一行和第二行
String[] memTotalArray = input.readLine().replace(" ", "").split(":");
String[] memFreeArray = input.readLine().replace(" ", "").split(":");

float memTotal = Float.valueOf(memTotalArray[1].replace("kB", ""));
float memFree = Float.valueOf(memFreeArray[1].replace("kB", ""));

System.out.println("memTotal = "+memTotal/(1024*1024) + "GB");
System.out.println("memFree = "+memFree/1024 + "MB");
HashMap<String, Float> mem = new HashMap<>();
mem.put("memTotal", memTotal);
mem.put("memFree", memFree);
return mem;
}
}

Apache Maven 入门篇 ( 上 )
本文着重动手,用 maven 来构建运行 hellow world 程序,体会一下不用任何 IDE ,只用 maven 是咋回事。

Apache Maven 入门篇(下)
* POM (Project Object Model)
* Maven 插件
* Maven 生命周期
* Maven 依赖管理
* Maven 库
我的 Maven Setting.xml 的mirrors配置

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
<mirrors>  

<mirror>
<id>aliyunmaven</id>
<name>aliyun public maven</name>
<url>https://maven.aliyun.com/repository/public</url>
<mirrorOf>public</mirrorOf>
</mirror>


<mirror>
<id>alimaven</id>
<name>aliyun central maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>

<mirror>
<id>ui</id>
<mirrorOf>central</mirrorOf>
<name>Human Readable Name for this Mirror.</name>
<url>http://uk.maven.org/maven2/</url>
</mirror>

<mirror>
<id>jboss-public-repository-group</id>
<mirrorOf>central</mirrorOf>
<name>JBoss Public Repository Group</name>
<url>http://repository.jboss.org/nexus/content/groups/public</url>
</mirror>



</mirrors>

https://github.com/haiwen/seafile

Seafile 的目标是给企业提供一个安全的云存储平台,满足企业文件的共享和协作的需求。

Seafile 采用开源的方式来进行产品开发。开源帮助 Seafile 成为了一个国际化的项目,并吸引了全球用户的参与和贡献。目前我们已经在 Github 开源代码托管平台上有了 3900 多个关注。全球用户的使用、反馈和审核使得 Seafile 更加的安全和稳定。

截至 2016 年初,Seafile 已经有超过 30 万用户使用,并拥有卡巴斯基,德国 Mainz 大学,德国 HU Berlin 大学和法国 Strasbourg 大学等大型组织机构客户。

https://www.seafile.com/home/

阅读全文 »

测试工具:
MQTTLens,MQTTBox

测试服务地址:

1
2
3
4
5
6
7
8
1. mosquitto
mqtt://test.mosquitto.org
ws://test.mosquitto.org:8080/mqtt (没连上)
测试页面:http://test.mosquitto.org/ws.html

2. eclipse
tcp://iot.eclipse.org
ws://iot.eclipse.org:80/ws

MQTT Client 比较多,各种语言都有开源项目,基本都是基于TCP/IP的,如Java/OC/Swift/nodejs/C/C++等。

H5上的js也可以使用MQTT,只不过是基于WebSocket,用法和其他语言的有一点点区别。

阅读全文 »

1
2
3
4
5
6
7
<script language="javascript">
function getarg(url){
arg=url.split("#");
return arg[1];
}
alert(getarg('http://www.iswtf.com/test.php#ID=58'));
</script>

昨天遇到这个问题:在A页面中通过location.href跳转到另一个B页面,此跳转地址是http://www.xyz.com/aa.html#bb.html?param=xxx 现在要怎么在B页面中取到param的值?现在的情况是跳到B页面后地址栏显示的就是http://www.xyz.com/aa.html#bb.html 后面的参数部分没有了,取到的参数值也是空的

搞了好久也没出来,最后问了大牛才发现我的基本功不行啊 理解就出错了,#后的内容都不会传到服务端的,所以到新页面看到的地址栏中就没有#后的参数,经大牛指点,把地址改为:
http://www.xyz.com/aa.html?param=xxx#bb.html 就是先加参数,再加# 因为这个页面是有iframe的,所以其实也是传参数到aa.html的,并不是bb.html
具体细看下下列的各对象说明就明白了
location:子对象
document.location.hash // #号后的部分
document.location.host // 域名+端口号
document.location.hostname // 域名
document.location.href // 完整URL
document.location.pathname // 目录部分
document.location.port // 端口号
document.location.protocol // 网络协议(http:)
document.location.search // ?号后的部分

然后到跳转后的页面处理这个地址就可以取到参数值了,方法:

再引用一下http://www.cnblogs.com/kaituorensheng/p/3776527.html内容,说明下#

阅读全文 »

https://www.uedsc.com/xenon.html

Xenon响应式后台管理模板,全套模板,包含后台登录页面、仪表盘、皮肤选择、布局、UI元素、按钮、标签和手风琴、模态、进度条、导航栏、警报、分页、小工具、邮箱、表格、表单、地图、画廊、图标、日历、图像裁切、404错误页、排行榜等共127个后台模板页面。

Xenon HTML模板是一款后台面板 HTML模板。
模板特点:4个仪表盘,28个布局,UI 元素,在线洽谈,时间轴,相册管理,皮肤创建,通告,各种应用元素,提供说明文档等。

阅读全文 »

问题:

  1. 前后端分离
  2. 前端在编写阶段(机器IP:192.168.1.11),后端已经部署好,数据通过REST API提供(机器IP:192.168.1.33:8000/api/)
  3. 跨域问题,就算是端口不一样也会出现。

解决跨域问题有多种,这里选择nginx代理。
####nginx配置

  1. nginx默认监听80端口,由于是编码阶段,我们不改动。

  2. 新建一个server监听8080,并且将http://localhost:8080/api全部转发到http://192.168.1.33:8000/api

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
      server {
    listen 8080;
    server_name localhost:8080;

    location / {
    root F:/html/myHtmlTest;
    index index.html index.htm;
    }
    location /api {
    proxy_pass http://192.168.1.33:8000/api;
    }
    }

    或者

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
      server {
    listen 8080;
    server_name localhost:8080;

    location / {
    root F:/html/myHtmlTest;
    index index.html index.htm;
    }
    location /api/ {
    proxy_pass http://192.168.1.33:8000;
    }
    }

    两种写法效果一样,区别在于

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    location /api {
    proxy_pass http://192.168.1.33:8000/api;
    }
    #这样写`proxy_pass`不会带上`location`的“/api ”,所以改成这样
    location /test{
    proxy_pass http://192.168.1.33:8000/api;
    }
    #目标访问地址也是不变的
    #但是我们访问就应该是 http://192.168.1.11:8080/test
    #转发到 http://192.168.1.33:8000/api
    1
    2
    3
    4
    5
    6
    location /api/ {
    proxy_pass http://192.168.1.33:8000;
    }
    #这种写法的`proxy_pass`会把`location`的“/api/ ”带上
    #当访问 http://192.168.1.11:8080/api/
    #就会转发为 http://192.168.1.33:8000/api/
  3. 前端html文件(如test.html)放在location /.root的目录下(如F:/html/myHtmlTest)

  4. 通过http://localhost:8080/test.html 访问html文件

  5. ajax访问资源 var url = “http://localhost:8080/api/v1/hello/“;

  6. nginx会将api转发到http://192.168.1.33:8000/api;

Linux下的配置文件include了其他默认的配置,可以在里面配置server,如果不需要可以注释掉。

阅读全文 »

在响应头加入

1
2
3
Access-Control-Allow-Headers →x-requested-with,content-type
Access-Control-Allow-Methods →POST
Access-Control-Allow-Origin →*

表示允许任何域名跨域访问,客户端访问示例 :传送门