如何定位 app is not installed 错误

这两天尝试着去了解下 Android 软件安全。我在 AVD 上一个 apk 无法被安装, 应该是与 apk 本身没有关系,因为这个 apk 就是我从豌豆荚上下载下来的,点击下一步后,直接提示 app is not installed ,在 Google 上搜索了一翻,为什么会出现这个问题,SO 上有提到一些原因,但是都不是我这里的情况。我重新搜索“app is not installed where is log”,这个问题 下面的一个回答提示了我使用

adb logcat

于是,使用上面命令,log 里面很清晰明显的暴露了问题所在。

感谢,logcat ,这是一只好猫。

Yii2 AssetBundle js 和 css 没有自动更新的问题

最近几天看了很多基于 Yii2 的一些开源项目。很多功能都在可以找到开源的以 Yii2 extension 的形式存在,集成到自己的项目中相当简单。这么说吧,基于这些组件,你可以写很少或者几乎不用写一行代码就可以搭建起来一套很好用的程序。常见的富文本编辑器、权限管理、导航栏、菜单等等这些都有很多不错的扩展可以直接集成。之前我一直以为PHP程序源码不含图片的话超过10M就很恐怖了,但最近几天接触的这些基于 Yii2 的项目,composer install 之后整个源码目录大小超过100M很常见。当然,这还没有 node 恐怖,npm install 之后,随随便便 200M+ 更常见。

以上是题外话。前段时间我就发现了如题的问题。那时没注意。今天仔细读了下相关源码,弄明白了这个问题的根源。

假设有如下 HelloAsset

<?php
namespace app\assets;

use yii\web\AssetBundle;

class HelloAsset extends AssetBundle
{

    public $sourcePath = '@app/hello_assets';

    public $js = [
        'hello.js',
        'js/hello2.js',
    ];

}

在视图文件里面注入这个 Bundle

<?php

\app\assets\HelloAsset::register($this);

?>

<h1>Hello, world!</h1>

问题表现为:当我们修改 hello.js 后,刷新页面,加载的是我们修改过后的最新的 js。但是当我们修改 js/hello2.js 的内容后,刷新页面,发现最新的 js 并没有出现在浏览器中。

一路追踪代码到 AssetManager.php 里面有个 hash 方法,这个方法会生成 bundle 对应的 assets 目录,代码如下:

    /**
     * Generate a CRC32 hash for the directory path. Collisions are higher
     * than MD5 but generates a much smaller hash string.
     * @param string $path string to be hashed.
     * @return string hashed string.
     */
    protected function hash($path)
    {
        if (is_callable($this->hashCallback)) {
            return call_user_func($this->hashCallback, $path);
        }
        $path = (is_file($path) ? dirname($path) : $path) . filemtime($path);
        return sprintf('%x', crc32($path . Yii::getVersion()));
    }

上面方法的参数 $path 就是 AssetBundle::$sourcePath 应用 Yii::getAlias 得到的路径。可以看到这个方法的逻辑很清晰,如果没有配置 hashCallback,默认生成 hash 与 $path 的最近一次修改时间相关。怀疑问题出现在这里。

linux 下用 stat 命令可以获取文件的最近访问更改以及改动时间:

$ stat hello_assets 
  文件:"hello_assets"
  大小:4096      	块:8          IO 块:4096   目录
设备:fc00h/64512d	Inode:1321721     硬链接:3
权限:(0775/drwxrwxr-x)  Uid:(  900/ vagrant)   Gid:(  900/ vagrant)
最近访问:2016-03-16 17:46:07.011451000 +0800
最近更改:2016-03-16 17:46:06.995443000 +0800
最近改动:2016-03-16 17:46:06.995443000 +0800
创建时间:-

当我更改 hello.js 的内容后再次运行 stat 命令:

$ stat hello_assets 
  文件:"hello_assets"
  大小:4096      	块:8          IO 块:4096   目录
设备:fc00h/64512d	Inode:1321721     硬链接:3
权限:(0775/drwxrwxr-x)  Uid:(  900/ vagrant)   Gid:(  900/ vagrant)
最近访问:2016-03-16 17:56:31.279429000 +0800
最近更改:2016-03-16 17:56:31.271425000 +0800
最近改动:2016-03-16 17:56:31.271425000 +0800
创建时间:-

很明显,最近改动时间已经变了,这点是没问题的。

当我更改 js/hello2.js 的内容后再运行 stat:

$ stat hello_assets            
  文件:"hello_assets"
  大小:4096      	块:8          IO 块:4096   目录
设备:fc00h/64512d	Inode:1321721     硬链接:3
权限:(0775/drwxrwxr-x)  Uid:(  900/ vagrant)   Gid:(  900/ vagrant)
最近访问:2016-03-16 17:56:31.279429000 +0800
最近更改:2016-03-16 17:56:31.271425000 +0800
最近改动:2016-03-16 17:56:31.271425000 +0800
创建时间:-

可以看到这时 stat hello_assets 的最近改动时间并没有变化。

所以得出结论,当我们更改 $sourcePath 下面再下一级目录下的文件时,$sourcePath 目录的 filemtime 时间并不会改变,因此 hash 函数生成的哈希值也就没有变化。进一步,AssetManager 就没有再进行 publish 资源文件。

解决这个问题的一个方案就是更换生成哈希的实现。我做了一个简单的实现,在配置文件里面 components 项配置 assetManager 的 hashCallback 属性

$config = [
    /*...*/
    'components' => [
        /*...*/
        'assetManager' => [
            'hashCallback' => function ($path) {

                if (!function_exists('_myhash_')) {
                    function _myhash_($path) {
                        if (is_dir($path)) {
                            $handle = opendir($path);
                            $hash = '';
                            while (false !== ($entry = readdir($handle))) {
                                if ($entry === '.' || $entry === '..') {
                                    continue;
                                }
                                $entry = $path . '/' . $entry;
                                $hash .= _myhash_($entry);
                            }
                            $result = sprintf('%x', crc32($hash . Yii::getVersion()));
                        } else {
                            $result = sprintf('%x', crc32(filemtime($path) . Yii::getVersion()));
                        }
                        return $result;
                    }
                }

                return _myhash_($path);
            }
        ],
        /*...*/
    ],
    /*...*/
];

 

Is this php’s bug?

I am reading yii2’s source code right now. I found that this method yii\di\Instance::ensure something werid。

I changed the code as following:

public static function ensure($reference, $type = null, $container = null)
{
// I added three lines
     $container = null;
     var_dump(get_class($container));
     die;
// original code
}

I got output as :

string(15) “yii\di\Instance”

Can anyone explain?

#Answer

Just now(2016-04-12 15:20:58),I asked Laruence about this questing in qq group.  He answered me that get_calss(null) will return current scope. Then I read the php documetation , It says:

If object is omitted when inside a class, the name of that class is returned.

So, RTFM si right.

记域名备案以及服务器迁到腾讯云上来

之前使用的 Linode 东京节点 1G VPS,在公司访问的时候挺快的,虽然偶尔也会出现 ping 不通,但是家里的长城宽带就是狗屎,基本上连不上去。擦~,当初安装宽带的时候,我就得想想,同样是 100M ,为啥长城要比电信便宜那么多呢,妈蛋,长城的 100M 是大中华局域网的 100M,访问境外网站基本跪。

前两天发现百度没有收录我的博客任何一个页面了,想了想应该是前段时间切换到 https 导致的,我启用了 https 并且把原先的 http 全部到 301 到 https 的链接上面来了。今天看了一下,百度收录了一些,但都是 http 的链接。谷歌收录现在全部都是 https。无所谓了,反正现在每天没有来自百度的任何流量。

朋友在腾讯云工作给推荐自家产品,给了我一个备案授权码,备案很顺利并且很快就通过了。今天购买了腾讯云1G VPS 1个,折腾环境折腾了好久,起初安装的是 CentOS7.1 编译出来的 php-7.0.2 在 nginx 里面没有任何输出也没有任何错误日志,我懒得折腾了,重新装了个 debian8.2,apt 安装 mysql-server 的时候又报错。最终还是换回了 ubuntu。

Linode 也用了18个月的时间,一直都是10美元一个月,最开始是512M 的内存,中间有一次给免费升级到1G 了。腾讯云目前是68元(65主机+3元数据盘)一个月,算下来价格差不多。不过腾讯的出口宽带只有1Mbps,Linode 比这个大多了,我 scp 将 Linode 上的数据弄到腾讯云这个主机上,速度都超过 20Mbps 了,下载速度能达到 2MB/s。不管怎样,腾讯云在访问上更便捷,应该能让省不少心。

对了,晚上我还尝试着去使用了下阿里云的 ACE,应该和新浪 SAE差不多的东西,但是没有新浪的好用,可惜新浪的不支持 https(要想支持 https,一年至少10000元)。按我现在博客的访问量,使用 SAE 这种方式应该只需要花很少很少的钱。

你有没有觉得现在我的博客访问速度杠杠的呢?

配置 nginx 访问 http 自动跳转 https

昨晚在 wosign 申请了个2年的 ssl 证书,很快就部署好了。

今天配置了下,让访问 http 的 url 自动跳转到 https。

相关配置如下即可:

listen 80;
listen 443 ssl;
ssl_certificate /PATH_TO_CRT;
ssl_certificate_key /PATH_TO_KEY;
server_name upliu.net;
if ($scheme != https) {
    rewrite ^/(.*) https://$server_name/$1 permanent;
}

同时监听 80 和 443 端口,并且给 443 端口加上 ssl 支持。当访问不是通过 https 过来的,则重定向到 https 的路径。

compile php with openssl on mac osx error

从源码手动编译 PHP 时出现如下错误:

Undefined symbols for architecture x86_64:
  "_PKCS5_PBKDF2_HMAC", referenced from:
      _zif_openssl_pbkdf2 in openssl.o
  "_TLSv1_1_client_method", referenced from:
      _php_openssl_setup_crypto in xp_ssl.o
  "_TLSv1_1_server_method", referenced from:
      _php_openssl_setup_crypto in xp_ssl.o
  "_TLSv1_2_client_method", referenced from:
      _php_openssl_setup_crypto in xp_ssl.o
  "_TLSv1_2_server_method", referenced from:
      _php_openssl_setup_crypto in xp_ssl.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [libs/libphp5.bundle] Error 1

解决办法

MakeFile 里面找到类似下面这一行:

EXTRA_LIBS = -lresolv -lmcrypt -lltdl -liconv-lm -lxml2 -lcurl -lssl -lcrypto

删除所有的 -lssl 和 -lcrypto 然后添加 libssl.dylib 和 libcrypto.dylib 的路径(如果你安装了 brew,那么则是 /usr/local/opt/openssl/lib/),重新运行 make 命令,done。

附上我修改后的 MakeFile EXTRA_LIBS 那一行:

EXTRA_LIBS = -lz -lresolv -lmcrypt -lltdl -lstdc++ -liconv -liconv -lpng -lz -lcurl -lz -lm -lxml2 -lz -licucore -lm -lcurl -lxml2 -lz -licucore -lm -licui18n -licuuc -licudata -licuio -lxml2 -lz -licucore -lm -lxml2 -lz -licucore -lm -lxml2 -lz -licucore -lm -lxml2 -lz -licucore -lm /usr/local/opt/openssl/lib/libssl.dylib /usr/local/opt/openssl/lib/libcrypto.dylib

 

蜗牛工作室介绍

蜗牛工作室承接各类web程序开发以及数据抓取分析类需求。

整站开发类需求报价不低于五千,如果您的预算低于五千请另寻他人。

设计定稿后蜗牛工作室开始开发并每隔一段时间(例如每隔一周)同步最新开发成果给客户演示。在此期间客户可以提出细微调整需求(如部分细节颜色,宽高度调节),如果更改涉及大的前端页面改动或者后台功能设计,客户需要为此额外付费。蜗牛工作室对开发完成的程序提供一次免费的安装部署服务。蜗牛工作室对开发完成的程序承诺永久免费 bug 修复。

蜗牛部分客户案例展示如下:

  1. 贝美玩具
  2. 深圳市维度设计有限公司