Gitment:使用github issues构建的Comments

发现了一个很有趣的博客评论系统,gitment。说它有趣,是应为它基于git issues。其思路在于为每篇文章new一个issue。综合实现了登陆,评论,点赞等功能,同时支持markdown/GFM和代码高亮,完美契合gitpage。

在github的官方说明中,这样的操作在github的使用范围内。

部署也很方便。

1.注册 OAuth Application

在github提供的OAuth Application入口注册一个新的OAuth Application。其中callback url填写域名。

2.使用gitment

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<div id="container"></div>
<link rel="stylesheet" href="https://imsun.github.io/gitment/style/default.css">
<script src="https://imsun.github.io/gitment/dist/gitment.browser.js"></script>
<script>
var gitment = new Gitment({
id: '页面 ID', // 可选。默认为 location.href
owner: '你的 GitHub ID',
repo: '存储评论的 repo',
oauth: {
client_id: '你的 client ID',
client_secret: '你的 client secret',
},
})
gitment.render('container')
</script>

这样可以跟进Gitment的迭代。其中的client ID和client secret来自OAuth Application。

3.初始化评论

接下来直接push你更新的博客。然后在你博客的评论框下登陆github,此处登陆的账号要与owner一致,然后点击initialize comments。

JS

Lua tcp demo

Lua

本来是应该昨天发的,今天补上。

算是最简单的socket例子。

client

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
local socket = require("socket")
host = "127.0.0.1"
port = 8383
-- open a tcp connect,
-- method socket.connect(), means client
c = assert (socket.connect (host, port))
c:send ("request...\n")
while (true) do
local s, status, partial = c:receive ()
print(s)
if status == "closed" then break end
c:send ("request...\n")
end
c:close ()

server

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
socket = require("socket");
-- IP & port
host = "127.0.0.1";
port = "8383";
-- method socket.bind(), means client
server = assert(socket.bind(host, port));
msg = "from server...\n";
while 1 do
print("server: waitting for connection...");
-- return a client representing
control = assert(server:accept());
while 1 do
command,status = control:receive();
if status == "closed" then break end
print(command);
control:send(msg);
end
end

Lua tcp

Lua

TCP

socket.tcp()

使用bind()-listen()方法后,将master TCP对象转化为一个server 对象;使用connect()方法后,将master TCP对象转化为一个client对象。

此外,master TCP对象仅仅提供了断开连接的close()方法。

@return 成功时,返回一个新的master TCP对象;异常时,返回nil,并显示错误信息。

server:accept()

等待远程server的连接,并返回一个代表这个连接的client对象。

@return 远程server连接成功时,返回一个client对象;timeout或者其他连接失败时,返回nil,并显示错误信息。

master:bind(address, port)

address可以是IP或者主机名,port必需是0~64k。如果address是“*”,系统会用INADDR_ANY常数注册地址。如果port是0,则自动分配端口。

@return 成功返回1,失败返回nil,打印错误信息。

master:close()

client:close()

server:close()

关闭该对象使用的socket连接,并对其他应用开放被这个对象注册的本地地址。

client:receive([pattern [, prefix]])

根据读取模式(pattern)从client对象中读取数据。模式遵循LUA的file I/O格式。

一些总结

ADB全称Android Debug Bridge, 是android sdk里的一个工具。

它的主要功能有:

  • 运行设备的shell(命令行)

  • 管理模拟器或设备的端口映射

  • 计算机和设备之间上传/下载文件

  • 将本地apk软件安装至模拟器或android设备

查看设备

1
adb devices

安装软件

1
adb install [-r] [-s]

卸载软件

1
adb uninstall [-k] <软件名>

从电脑上发送文件到设备

1
adb push <本地路径> <远程路径>

用push命令可以把本机电脑上的文件或者文件夹复制到设备(手机)
例:传送文件到手机中,如:

1
adb push recovery.img /sdcard/recovery.img
adb

Http请求方式

Get

GET请求的数据会附在URL之后(就是把数据放置在HTTP协议头中),以?分割URL和传输数据,参数之间以&相连,如:http://api.juheapi.com/japi/toh?key=eff36bdaeeb868a6b8057a34f32d1326&v=1.0&month=11&day=1。

GET请求发送的参数如果数据是英文字母或数字,则按原样发送,如果是空格,则转换为+,如果是中文或其他字符,则直接把字符串用BASE64加密,得出如 %E4%BD%A0%E5%A5%BD 这类似的字符串,其中%XX中的XX为该符号以16进制表示的ASCII。

Post

POST请求的参数不是放在URL字符串里面,而是放在HTTP请求的正文内,请求的参数被封装起来以流的形式发送给服务端。

Get or Post?

对于GET方式提交数据的大小,HTTP协议并没有硬性限制,但某些浏览器及服务器会对它进行限制,如IE对URL长度的限制是2083字节(2K+35)。理论上POST也没有限制,可传较大量的数据。

POST的安全性要比GET的安全性高。比如:通过GET提交数据,用户名和密码将明文出现在URL上,因为登录页面有可能被浏览器缓存,如果其他人查看浏览器的历史纪录,那么别人就可以拿到你的账号和密码了,除此之外,使用GET提交数据还可能会造成Cross-site request forgery(CSRF,跨站请求伪造)攻击。

一般来说,Get是向服务器索取数据的一种请求,而Post是向服务器提交数据的一种请求。

生成so文件

配置NDK环境变量

找到Android Studio安装的NDK包的文件目录(E:AndroidStudioSDKSDKndk-bundle),添加到系统的环境变量中

新建mk文件

在jni目录下新建Android.mk

1
2
3
4
5
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := JNISample
LOCAL_SRC_FILES := com_lilei_testjni_JniUtils.cpp
include $(BUILD_SHARED_LIBRARY)

在jni目录下新建Application.mk文件

1
2
3
4
APP_STL := gnustl_static
APP_CPPFLAGS := -frtti -fexceptions -std=c++0x
APP_ABI := armeabi-v7a
APP_PLATFORM := android-18

编译生成so

打开终端cd到jni目录下
调用ndk-build开始编译so

1
ndk-build

运行成功之后即会看到main文件夹下多了libs和obj的文件夹,里面就是生成的各种CPU的so文件

jni

环境配置

主要需要配置的就是NDK(Native Development Kit),现在Android studio很便利,可以一键下载: file → setting → 按截图找到如下路径 → 选择NDK → 确定应用下载

设置项目支持JNI

打开gradle.properties,添加:

1
android.useDeprecatedNdk=true

打开local.properties,添加:

1
ndk.dir=NDK的路径

最后打开app内build.gradle,在android/defaultConfig下面添加ndk配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
android {
compileSdkVersion 25
buildToolsVersion "25.0.0"
defaultConfig {
applicationId "com.lilei.testjni"
minSdkVersion 15
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
ndk {
moduleName "JNISample"
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}

新建java访问c层的接口类

创建一个Jni的工具类,并定义接口函数,函数关键字用native(static用不用均可)

1
2
3
4
5
6
7
package com.lilei.testjni;
/**
* Created by lilei on 2017/3/29.
*/
public class JniUtils {
public static native String getJniString();
}

生成头文件

打开终端,运行

1
2
cd app/build/intermediates/classes/debug/
javah com.lilei.testjni.JniUtils

运行成功之后打开app/build/intermediates/classes/debug/ 即可找到编译出的头文件”com_lilei_testjni_JniUtils.h”,不难发现头文件名是有原报名+类名组成

创建jni开发的文件夹

点击app文件夹,New → Folder → JNI Folder, 选择在main文件夹下即可,生成成功后main目录下会出现一个jni的文件夹
找到刚才生成到头文件,复制到jni文件夹下(记得关闭刚才使用的终端,否则无法复制)
头文件有了,现在在jni目录下创建一个C++文件用于开发使用,命名与头文件相同
编写C++文件中定义函数的代码

1
2
3
4
5
6
#include "com_lilei_testjni_JniUtils.h"
JNIEXPORT jstring JNICALL Java_com_lilei_testjni_JniUtils_getJniString
(JNIEnv *env, jclass) {
// new 一个字符串,返回Hello World
return env -> NewStringUTF("Hello World");
}

java层加载so

回到JniUtils,加上

1
2
3
static {
System.loadLibrary("JNISample");
}

运行Run

调用jni的函数

1
2
3
4
5
6
7
8
9
10
11
12
package com.lilei.testjni;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.i("Jni", JniUtils.getJniString());
}
}

至此就成功运行出jni的Hello World了