Android 通过应用包名启动外部应用
void startFit(String packageName) { PackageManager packageManager = this.getApplicationContext().getPackageManager(); PackageInfo pi = null; try { pi = packageManager.getPackageInfo(packageName, 0); if(pi == null) { Toast.makeText(FullscreenLauncher.this, "应用未安装", Toast.LENGTH_SHORT).show(); return; } } catch (PackageManager.NameNotFoundException e) { } Intent resolveIntent = new Intent(Intent.ACTION_MAIN, null); resolveIntent.addCategory(Intent.CATEGORY_LAUNCHER); resolveIntent.setPackage(pi.packageName); List<ResolveInfo> apps = packageManager.queryIntentActivities(resolveIntent, 0); ResolveInfo ri = apps.iterator().next(); if (ri != null ) { String className = ri.activityInfo.name; Intent intent = new Intent(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_LAUNCHER); ComponentName cn = new ComponentName(packageName, className); intent.setComponent(cn); this.getApplicationContext().startActivity(intent); } }
Redmine与Gitblit联动(二)
如果git仓库在本机上就更方便了,不用迁出直接配置成对应的git仓库地址,如果在仓库另一台机子上,则需要如下操作做一个git mirror
新建一个 gitrespo ,然后将所属用户改成www-data以完成权限设定
然后 git clone –mirror
299 sudo mkdir /gitrespo
300 ll
301 cd /gitrespo/
302 mv /gitrespo/ /gitrepos
303 sudo mv /gitrespo/ /gitrepos
304 ll
305 cd ..
306 ll
307 cd /gitrepos/
308 ll
309 chmod -R 777 ./
310 sudo chmod -R 777 ./
311 sudo chown -R www-data:www-data gitrepos
312 sudo chown -R www-data:www-data ./
313 ll
314 sudo -u www-data -H git clone –mirror git://192.168.8.18/FitPose.git
319 cd FitPose.git/
320 git fetch
以上完成了迁出与git mirror操作,接下来就需要在Redmine上进行配置仓库的地址
修改git源代码的 git adapter.rb 主要是以下这段
def branches return @branches if @branches @branches = [] cmd_args = %w|branch --no-color --verbose --no-abbrev| git_cmd(cmd_args) do |io| io.each_line do |line| branch_rev = line.match('\s*(\*?)\s*(.*?)\s*([0-9a-f]{40}).*$') next unless branch_rev bran = GitBranch.new(branch_rev[2]) bran.revision = branch_rev[3] bran.scmid = branch_rev[3] bran.is_default = ( branch_rev[1] == '*' ) @branches << bran end end logger.info "1. fetch --all" cmd_args = %w|fetch --all| git_cmd(cmd_args) do |io| logger.info io.readlines end logger.info "2. reset --hard origin" cmd_args = %w|reset --hard origin| git_cmd(cmd_args) do |io| logger.info io.readlines end @branches.sort! rescue ScmCommandAborted nil end
def git_cmd(args, options = {}, &block) repo_path = root_url || url full_args = ['-C', repo_path + '/..', '--git-dir', repo_path] if self.class.client_version_above?([1, 7, 2]) full_args << '-c' << 'core.quotepath=false' full_args << '-c' << 'log.decorate=no' end full_args += args cmdline = self.class.sq_bin + ' ' + full_args.map { |e| shell_quote e.to_s }.join(' ') logger.info cmdline ret = shellout( cmdline, options, &block ) if $? && $?.exitstatus != 0 raise ScmCommandAborted, "git exited with non-zero status: #{$?.exitstatus}" end logger.info "execute end" ret end private :git_cmd
以下是修改后的 git_adapter.rb
git_adapter.rb
修改替换后,重启redmine即可
342 ./ctlscript.sh restart apache
Redmine与Gitblit联动
配置好redmine后,访问redmine地址,用管理员帐号登录,点击顶上的管理TAB菜单,左边的选项中选择信息,可以看到当前Redmine的各种环境的版本,本次搭建的最新版本(2019-11-07)如下
Environment:
Redmine version 4.0.5.stable
Ruby version 2.5.7-p206 (2019-10-01) [x86_64-linux]
Rails version 5.2.3
Environment production
Database adapter Mysql2
Mailer queue ActiveJob::QueueAdapters::AsyncAdapter
Mailer delivery smtp
SCM:
Subversion 1.12.2
Git 2.19.1
Filesystem
Step1:在管理->配置->API 中,勾选开启Webservice
Step2:在管理->配置 ->版本库中,开启自动获取程序变更与WebService,并生成一个key密钥。因为是内网布署的,所以亮出密钥了:P
Step3:在Gitblit目录中配置apkkey与url
修改${gitblit-1.8.0-dir}/data/groovy/redmine-fetch.groovy文件以下行
/* specify the URL of your Redmine instance here */
def redmineURL = "http://192.168.8.31:8080/redmine/"
/* specify the URL of your Redmine instance here */
def apiKey = "LNOcmjUSy0Dxxu3Dpjxi"
Step4:在Gitblit版本库->编辑->receive 中Selected加入redmine–fetch
Step5:待续
参考https://blog.csdn.net/weixin_33953384/article/details/91693565
OpenCV 下 op::putText 显示中文的方法
//头上加入 #include <hstring.h>
//方法开始 void GetStringSize(HDC hDC, const char* str, int* w, int* h) { SIZE size; GetTextExtentPoint32A(hDC, str, strlen(str), &size); if (w != 0) * w = size.cx; if (h != 0) * h = size.cy; } void paDrawString(cv::Mat& dst, const char* str, cv::Point org, cv::Scalar color, int fontSize, bool italic, bool underline) { CV_Assert(dst.data != 0 && (dst.channels() == 1 || dst.channels() == 3)); int x, y, r, b; if (org.x > dst.cols || org.y > dst.rows) return; x = org.x < 0 ? -org.x : 0; y = org.y < 0 ? -org.y : 0; LOGFONTA lf; lf.lfHeight = -fontSize; lf.lfWidth = 0; lf.lfEscapement = 0; lf.lfOrientation = 0; lf.lfWeight = 5; lf.lfItalic = italic; //斜体 lf.lfUnderline = underline; //下划线 lf.lfStrikeOut = 0; lf.lfCharSet = DEFAULT_CHARSET; lf.lfOutPrecision = 0; lf.lfClipPrecision = 0; lf.lfQuality = PROOF_QUALITY; lf.lfPitchAndFamily = 0; //此处可定义使用的字体 strcpy(lf.lfFaceName, "宋体"); HFONT hf = CreateFontIndirectA(&lf); HDC hDC = CreateCompatibleDC(0); HFONT hOldFont = (HFONT)SelectObject(hDC, hf); int strBaseW = 0, strBaseH = 0; int singleRow = 0; char buf[1 << 12]; strcpy(buf, str); //处理多行 { int nnh = 0; int cw, ch; const char* ln = strtok(buf, "\n"); while (ln != 0) { GetStringSize(hDC, ln, &cw, &ch); strBaseW = std::max(strBaseW, cw); strBaseH = std::max(strBaseH, ch); ln = strtok(0, "\n"); nnh++; } singleRow = strBaseH; strBaseH *= nnh; } if (org.x + strBaseW < 0 || org.y + strBaseH < 0) { SelectObject(hDC, hOldFont); DeleteObject(hf); DeleteObject(hDC); return; } r = org.x + strBaseW > dst.cols ? dst.cols - org.x - 1 : strBaseW - 1; b = org.y + strBaseH > dst.rows ? dst.rows - org.y - 1 : strBaseH - 1; org.x = org.x < 0 ? 0 : org.x; org.y = org.y < 0 ? 0 : org.y; BITMAPINFO bmp = { 0 }; BITMAPINFOHEADER& bih = bmp.bmiHeader; int strDrawLineStep = strBaseW * 3 % 4 == 0 ? strBaseW * 3 : (strBaseW * 3 + 4 - ((strBaseW * 3) % 4)); bih.biSize = sizeof(BITMAPINFOHEADER); bih.biWidth = strBaseW; bih.biHeight = strBaseH; bih.biPlanes = 1; bih.biBitCount = 24; bih.biCompression = BI_RGB; bih.biSizeImage = strBaseH * strDrawLineStep; bih.biClrUsed = 0; bih.biClrImportant = 0; void* pDibData = 0; HBITMAP hBmp = CreateDIBSection(hDC, &bmp, DIB_RGB_COLORS, &pDibData, 0, 0); CV_Assert(pDibData != 0); HBITMAP hOldBmp = (HBITMAP)SelectObject(hDC, hBmp); //color.val[2], color.val[1], color.val[0] SetTextColor(hDC, RGB(255, 255, 255)); SetBkColor(hDC, 0); //SetStretchBltMode(hDC, COLORONCOLOR); strcpy(buf, str); const char* ln = strtok(buf, "\n"); int outTextY = 0; while (ln != 0) { TextOutA(hDC, 0, outTextY, ln, strlen(ln)); outTextY += singleRow; ln = strtok(0, "\n"); } uchar* dstData = (uchar*)dst.data; int dstStep = dst.step / sizeof(dstData[0]); unsigned char* pImg = (unsigned char*)dst.data + org.x * dst.channels() + org.y * dstStep; unsigned char* pStr = (unsigned char*)pDibData + x * 3; for (int tty = y; tty <= b; ++tty) { unsigned char* subImg = pImg + (tty - y) * dstStep; unsigned char* subStr = pStr + (strBaseH - tty - 1) * strDrawLineStep; for (int ttx = x; ttx <= r; ++ttx) { for (int n = 0; n < dst.channels(); ++n) { double vtxt = subStr[n] / 255.0; int cvv = vtxt * color.val[n] + (1 - vtxt) * subImg[n]; subImg[n] = cvv > 255 ? 255 : (cvv < 0 ? 0 : cvv); } subStr += 3; subImg += dst.channels(); } } SelectObject(hDC, hOldBmp); SelectObject(hDC, hOldFont); DeleteObject(hf); DeleteObject(hBmp); DeleteDC(hDC); }
调用时替换原有的 cv:putText
paDrawString(*show_img, labelstr, pt_text, black_color, 12, 0, 0); //cv::putText(*show_img, labelstr, pt_text, cv::FONT_HERSHEY_COMPLEX_SMALL, font_size, black_color, 2 * font_size, CV_AA);
yarn VS npm 的优势
安装速度快 。
- 并行安装:无论 npm 还是 Yarn 在执行包的安装时,都会执行一系列任务。npm 是按照队列执行每个 package,也就是说必须要等到当前 package 安装完成之后,才能继续后面的安装。而 Yarn 是同步执行所有任务,提高了性能。
- 离线模式:如果之前已经安装过一个软件包,用Yarn再次安装时之间从缓存中获取,就不用像npm那样再从网络下载了。
- 安装版本统一:为了防止拉取到不同的版本,Yarn 有一个锁定文件 (lock file) 记录了被确切安装上的模块的版本号。每次只要新增了一个模块,Yarn 就会创建(或更新)yarn.lock 这个文件。这么做就保证了,每一次拉取同一个项目依赖时,使用的都是一样的模块版本。npm 其实也有办法实现处处使用相同版本的 packages,但需要开发者执行 npm shrinkwrap 命令。这个命令将会生成一个锁定文件,在执行 npm install 的时候,该锁定文件会先被读取,和 Yarn 读取 yarn.lock 文件一个道理。npm 和 Yarn 两者的不同之处在于,Yarn 默认会生成这样的锁定文件,而 npm 要通过 shrinkwrap 命令生成 npm-shrinkwrap.json 文件,只有当这个文件存在的时候,packages 版本信息才会被记录和更新。
- 更简洁的输出:npm 的输出信息比较冗长。在执行 npm install <package> 的时候,命令行里会不断地打印出所有被安装上的依赖。相比之下,Yarn 简洁太多:默认情况下,结合了 emoji直观且直接地打印出必要的信息,也提供了一些命令供开发者查询额外的安装信息。
- 多注册来源处理:所有的依赖包,不管他被不同的库间接关联引用多少次,安装这个包时,只会从一个注册来源去装,要么是 npm 要么是 bower, 防止出现混乱不一致。
- 更好的语义化: yarn改变了一些npm命令的名称,比如 yarn add/remove,感觉上比 npm 原本的 install/uninstall 要更清晰。
FFMpeg 提取关键帧命令
ffmpeg.exe -i D:\DShare\f2.mp4 -vf select=’eq(pict_type\,I)’,setpts=’N/(25*TB)’ D:\DShare\output\%09d.jpg
Anaconda 安装 tensorflow
Anaconda 安装 tensorflow
pip install –upgrade -i https://pypi.tuna.tsinghua.edu.cn/simple –ignore-installed tensorflow
Anaconda 安装 tensorflowGPU
pip install –upgrade -i https://pypi.tuna.tsinghua.edu.cn/simple –ignore-installed tensorflow-gpu
Android ADB 命令行控制屏幕
禁用自动旋转 adb shell content insert --uri content://settings/system --bind name:s:accelerometer_rotation --bind value:i:0
启用自动旋转 adb shell content insert --uri content://settings/system --bind name:s:accelerometer_rotation --bind value:i:1
旋转屏幕 adb shell content insert --uri content://settings/system --bind name:s:user_rotation --bind value:i:1
旋转屏幕的值 可以为 0,1,2,3,对应四个方向
Ubuntu 16.04下 CPU 性能模式切换
查看CPU当前频率
cat /proc/cpuinfo | grep MHz
1、安装cpufrequtils:
sudo apt-get install cpufrequtils
2、查看当前cpu的状态:
cpufreq-info
3、把cpu调整到性能模式:
sudo cpufreq-set -g performance
使用上述方式,重启系统后又回到默认方式。修改默认模式:
1、安装sysfsutils
sudo apt-get install sysfsutils
2、编辑/etc/sysfs.conf ,增加如下语句:
devices/system/cpu/cpu0/cpufreq/scaling_governor = performance
可选的有
1. performance:CPU维持最高时脉运行。
2. ondemand:程序运行时,直接调高时脉运行。(但不一定是调到最高,而是依程式需求)。没有运行时,调低时脉。
3. conservative:同上,但调整的方式,是一阶一阶地调整,而非直接调整。
4. powersave:CPU维持最低时脉运行
5. userspace:是由使用者自己定义,需要安装其他软件管理
NodeJS Request与文件上传下载流相关
本文转载自 https://segmentfault.com/a/1190000000385867
使用超简单
Request使用超简单,同时支持https和重定向。
var request = require('request');
request('http://www.google.com', function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body) // 打印google首页
}
})
流
任何响应都可以输出到文件流。
request('http://google.com/doodle.png').pipe(fs.createWriteStream('doodle.png'))
反过来,也可以将文件传给PUT或POST请求。未提供header的情况下,会检测文件后缀名,在PUT请求中设置相应的content-type
。
fs.createReadStream('file.json').pipe(request.put('http://mysite.com/obj.json'))
请求也可以pipe
给自己。这种情况下会保留原content-type
和content-length
。
request.get('http://google.com/img.png').pipe(request.put('http://mysite.com/img.png'))
表单
request
支持application/x-www-form-urlencoded
和multipart/form-data
实现表单上传。
x-www-form-urlencoded
很简单:
request.post('http://service.com/upload', {form:{key:'value'}})
或者:
request.post('http://service.com/upload').form({key:'value'})
使用multipart/form-data
不用操心设置header之类的琐事,request
会帮你解决。
var r = request.post('http://service.com/upload')
var form = r.form()
form.append('my_field', 'my_value')
form.append('my_buffer', new Buffer([1, 2, 3]))
form.append('my_file', fs.createReadStream(path.join(__dirname, 'doodle.png'))
form.append('remote_file', request('http://google.com/doodle.png'))
HTTP认证
request.get('http://some.server.com/').auth('username', 'password', false);
或
request.get('http://some.server.com/', {
'auth': {
'user': 'username',
'pass': 'password',
'sendImmediately': false
}
});
sendImmediately
,默认为真,发送一个基本的认证header。设为false
之后,收到401
会重试(服务器的401响应必须包含WWW-Authenticate
指定认证方法)。
sendImmediately为真时支持Digest认证。
OAuth登录
// Twitter OAuth
var qs = require('querystring')
, oauth =
{ callback: 'http://mysite.com/callback/'
, consumer_key: CONSUMER_KEY
, consumer_secret: CONSUMER_SECRET
}
, url = 'https://api.twitter.com/oauth/request_token'
;
request.post({url:url, oauth:oauth}, function (e, r, body) {
// Ideally, you would take the body in the response
// and construct a URL that a user clicks on (like a sign in button).
// The verifier is only available in the response after a user has
// verified with twitter that they are authorizing your app.
var access_token = qs.parse(body)
, oauth =
{ consumer_key: CONSUMER_KEY
, consumer_secret: CONSUMER_SECRET
, token: access_token.oauth_token
, verifier: access_token.oauth_verifier
}
, url = 'https://api.twitter.com/oauth/access_token'
;
request.post({url:url, oauth:oauth}, function (e, r, body) {
var perm_token = qs.parse(body)
, oauth =
{ consumer_key: CONSUMER_KEY
, consumer_secret: CONSUMER_SECRET
, token: perm_token.oauth_token
, token_secret: perm_token.oauth_token_secret
}
, url = 'https://api.twitter.com/1/users/show.json?'
, params =
{ screen_name: perm_token.screen_name
, user_id: perm_token.user_id
}
;
url += qs.stringify(params)
request.get({url:url, oauth:oauth, json:true}, function (e, r, user) {
console.log(user)
})
})
})
定制HTTP header
User-Agent
之类可以在options
对象中设置。在下面的例子中,我们调用github API找出某仓库的收藏数和派生数。我们使用了定制的User-Agent
和https.
var request = require('request');
var options = {
url: 'https://api.github.com/repos/mikeal/request',
headers: {
'User-Agent': 'request'
}
};
function callback(error, response, body) {
if (!error && response.statusCode == 200) {
var info = JSON.parse(body);
console.log(info.stargazers_count + " Stars");
console.log(info.forks_count + " Forks");
}
}
request(options, callback);
cookies
默认情况下,cookies是禁用的。在defaults
或options
将jar
设为true
,使后续的请求都使用cookie.
var request = request.defaults({jar: true})
request('http://www.google.com', function () {
request('http://images.google.com')
})
通过创建request.jar()
的新实例,可以使用定制的cookie,而不是request
全局的cookie jar。
var j = request.jar()
var request = request.defaults({jar:j})
request('http://www.google.com', function () {
request('http://images.google.com')
})
或者
var j = request.jar()
var cookie = request.cookie('your_cookie_here')
j.setCookie(cookie, uri, function (err, cookie){})
request({url: 'http://www.google.com', jar: j}, function () {
request('http://images.google.com')
})
注意,setCookie
至少需要三个参数,最后一个是回调函数。