之前写过一篇 android 去网络感叹号的文章,但是实测文中提到的方法在android 7.X系统中已经失效。

原理:
7.1.1更改了验证方式,导致之前的修改方法失效,升级为7.1.1后wifi的叉叉和4g的叹号又回来了。

解决方法:

adb shell settings put global captive_portal_https_url https://captive.v2ex.co/generate_204

完事后重启就能看到效果。如果还是不行,请检查网络是否正常

前不久遇到了一个极光推送的问题,java后台在进行消息推送的时候,安卓这边会同时收到通知和自定义消息,当时搞得很郁闷。

后来java后台发现了问题所在:

qq20160811

如此就能解决同时推送通知和自定义消息的问题了!

 

也许你也遇到了这个问题,我希望你能花几分钟时间看看,也许会对你有所帮助

今天写文章的时候发现点击发布的时候,chrome浏览器提示无法连接,浏览器地址栏提示是提交给post.php这个文件,于是上百度搜索答案,然后打开了wordpress的debug模式,然后发现是wptouch mobile plugin的问题。

咋一看,以前从来没遇到过这种问题呀!再一想,不对,服务器上的php版本前不久从5.X升级到了7.X,同时也在php.net网站上面找到了一篇名为Deprecated features in PHP 7.0.x的文章,然后恍然大悟,估计这个作者没有“适配”php 7.x。。。停用了这个插件后一切都正常了~

最后别忘了关闭debug模式

由于伟大的gfw的干涉,原来挂靠在日本樱花的博客已经很难打开了,于是这次决定搬家了!

这次搬家到了香港,又回到了博客最初诞生的地方,想想也挺唏嘘的

support-v4中的fragment在现在看来显得有些老旧,因为现在的手机绝大部分都是4.X系统以上了,所以v4包中的fragment其实可以甩掉了。本文教你如何从v4包的fragment转换到原生fragment

首先你要确定一件事情——你想要你的app兼容到哪个系统。如果你想放弃过时的2.X系统,那么就请继续往下看吧

从v4的fragment转换到原生的fragment其实并不困难,有几点需要注意:

1)导入的包:

请将android.support.v4.app.fragment替换为android.app.fragment;

同样的,FragmentManager请替换为android.app.FragmentManager,以及FragmentTransaction

2)修改Activity:

一般情况下继承AppCompatActivity即可,这个也是AS默认的Activity继承类

3)如果使用了viewpager的话,请不要改动viewpager的引用

4)调用viewpager的setAdapter方法的时候,需要实现一个继承于android.support.v13.app.FragmentStatePagerAdapter的适配器,而这个类的引用方式需要引入v13的包:

compile ‘com.android.support:support-v13:23.3.0’

基本就是以上注意点,除此之外的用法均和support-v4中的一致。如果还有其他注意要点的话我会继续补充~

一句命令解决问题:

电脑端有adb的话

adb shell settings put global captive_portal_server g.cn

手机上操作的话需要有root,拿到手机的shell后

su

settings put global captive_portal_server g.cn

然后重启下手机

从此能正常使用的网络不会再跳出登录到XXX网络的烦人提示了,除了一些需要登录的免费热点

===============================================

2016年9月15日更新:

手机刷了Android 7.0 后发现此方法失效!7.0系统请移步:Android 7.X 去掉网络感叹号 

 

公司给配了一台Dell Inspiron  3558用于外出办公。由于工作需求又安装了Ubuntu 14.04,结果发现就触摸板没反应。为了能把触摸板用起来,找了很多方法都不奏效,最后在Google上找到这么个解决方案:

参考地址:http://askubuntu.com/questions/592925/dell-inspiron-3551-unresponsive-touchpad

主要思路是关闭i2c_hid并且在启动的时候加入nopnp参数(i2c_hid是啥我也没搞明白)

首先:sudo gedit /etc/default/grub

然后再gedit里面找到这么一行:

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"

把它改成:
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash i8042.nopnp"
保存后执行:
sudo update-grub
然后再运行这4条语句:

echo "blacklist i2c_hid" | sudo tee /etc/modprobe.d/i2c-hid.conf
sudo depmod -a
sudo update-initramfs -u
echo "synaptics_i2c" | sudo tee -a /etc/modules

重启,然后就能发现触摸板居然能用了!

再贴一下英文原文:

 

You can fix it by switching off i2c_hid and setting nopnp in boot parameters this way

  1. Run

sudo gedit /etc/default/grub

In the open window edit line

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"

it should look this way

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash i8042.nopnp"

Save file and run

sudo update-grub
  1. Run
    echo "blacklist i2c_hid" | sudo tee /etc/modprobe.d/i2c-hid.conf
    sudo depmod -a
    sudo update-initramfs -u
    echo "synaptics_i2c" | sudo tee -a /etc/modules
    
  2. Reboot.

在Android5.0以前的版本中,可以通过简单的反射机制来直接控制手机网络的打开与关闭:

ConnectivityManager connectivityManager =
        (ConnectivityManager) pContext.getSystemService(Context.CONNECTIVITY_SERVICE);
Method setMobileDataEnabl;
try {
    setMobileDataEnabl = connectivityManager.getClass().getDeclaredMethod("setMobileDataEnabled", boolean.class);
    setMobileDataEnabl.invoke(connectivityManager, pBoolean);
} catch (Exception e) {
    e.printStackTrace();
    Log.e("MobileUtil", "移动数据设置错误:" + e.toString());
}

但是,在Android5.0版本及以上,这方法就失效了,于是在StackOverFlow上面有大神提出一个解决方案,前提是手机必须能获取到Root权限:

private static void executeCommandViaSu(Context context, String option, String command) {
    boolean success = false;
    String su = "su";
    for (int i=0; i < 3; i++) {
        // Default "su" command executed successfully, then quit.
        if (success) {
            break;
        }
        // Else, execute other "su" commands.
        if (i == 1) {
            su = "/system/xbin/su";
        } else if (i == 2) {
            su = "/system/bin/su";
        }
        try {
            // Execute command as "su".
            Runtime.getRuntime().exec(new String[]{su, option, command});
        } catch (IOException e) {
            success = false;
            // Oops! Cannot execute `su` for some reason.
            // Log error here.
        } finally {
            success = true;
        }
    }
}
public static void setMobileNetworkfromLollipop(Context context,boolean ii) throws Exception {
    String command = null;
    int state=0;
    if(ii){
        state=1;
    }
    try {
        String transactionCode = getTransactionCode(context);
        // Android 5.1+ (API 22) and later.
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
            SubscriptionManager mSubscriptionManager = (SubscriptionManager) context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
            // Loop through the subscription list i.e. SIM list.
            for (int i = 0; i < mSubscriptionManager.getActiveSubscriptionInfoCountMax(); i++) {
                if (transactionCode != null && transactionCode.length() > 0) {
                    // Get the active subscription ID for a given SIM card.
                    int subscriptionId = mSubscriptionManager.getActiveSubscriptionInfoList().get(i).getSubscriptionId();
                    // Execute the command via `su` to turn off
                    // mobile network for a subscription service.
                    command = "service call phone " + transactionCode + " i32 " + subscriptionId + " i32 " + state;
                    executeCommandViaSu(context, "-c", command);
                }
            }
        } else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP) {
            // Android 5.0 (API 21) only.
            if (transactionCode != null && transactionCode.length() > 0) {
                // Execute the command via `su` to turn off mobile network.
                command = "service call phone " + transactionCode + " i32 " + state;
                executeCommandViaSu(context, "-c", command);
            }
        }
    } catch(Exception e) {
        // Oops! Something went wrong, so we throw the exception here.
        throw e;
    }
}
private static String getTransactionCode(Context context) throws Exception {
    try {
        final TelephonyManager mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        final Class<?> mTelephonyClass = Class.forName(mTelephonyManager.getClass().getName());
        final Method mTelephonyMethod = mTelephonyClass.getDeclaredMethod("getITelephony");
        mTelephonyMethod.setAccessible(true);
        final Object mTelephonyStub = mTelephonyMethod.invoke(mTelephonyManager);
        final Class<?> mTelephonyStubClass = Class.forName(mTelephonyStub.getClass().getName());
        final Class<?> mClass = mTelephonyStubClass.getDeclaringClass();
        final Field field = mClass.getDeclaredField("TRANSACTION_setDataEnabled");
        field.setAccessible(true);
        return String.valueOf(field.getInt(null));
    } catch (Exception e) {
        // The "TRANSACTION_setDataEnabled" field is not available,
        // or named differently in the current API level, so we throw
        // an exception and inform users that the method is not available.
        throw e;
    }
}

当代码中调用setMobileNetworkfromLollipop方法时,系统会提示应用要获取Root权限,其实这个方法的本质就是在Linux的终端中输入了svc data enable。。。 没有Root的机器是暂时没有解决办法的,因为只有root身份才能执行svc data enable。不知道这是不是Google故意把那个非公开api去掉了,不过回过头想想,不能直接使用这个方法也是为了考虑到系统的安全性,毕竟这个被滥用后会是一件非常麻烦的事 如果有别的方案可以开启数据连接的话欢迎提出来

最近从Eclipse转到Android Studio后,发现了不少的问题,其中一个让人头疼的问题是不能用AS来Debug,这一点是无法让我接受的。趁着周末有空就研究一下这个问题。

调试用的手机是小米3电信/联通版,AS版本是1.3.2 build 141.2178183,具体的问题如下:

QQ20150927213926

AS中点击Debug选择设备后就卡在了这里:Waiting for process:

相应的,手机上则卡在了这个界面:

Screenshot_com.example.luci.myapplication_2015-09-27-21-40-39

只是偶尔一两次可以进行Debug,如果点击Run则一点问题都没有。Oh no!

起初怀疑是手机问题,但是很快就被我否定了,因为之前用Eclipse调试的时候没出现过这种问题,而且手机插在别的有AS的电脑上也没出现这种问题。

于是怀疑是电脑问题,为此我特意准备了一个虚拟机,安装同样的操作系统,用同样的软件搭建同样的编程环境,却发现在虚拟机中一切正常,能正常调试!看来是电脑的问题了

然后开始怀疑驱动,由于之前用的是刷机精灵的驱动,于是我把驱动删了,换上了国外的某个软件下载的驱动,尝试后发现不行。删除驱动后我下载了我最反感的360,让这货给我装驱动。结果这个360驱动居然也不行。。。

百思不得其解后,百度找了下,找到一篇帖子提到了这个问题。按照帖子里讲的,禁用MDB设备,结果无效。。。到此我心想,换台手机试试呢?于是我找出了N年前的一台2.3.5系统的手机插上去后居然能正常调试,非常好使,至此我开始迷糊了。。。

在Goodle上找了一会儿,就找到一个StackOverflow上说项目的设置问题,把android:debug去掉即可。但是我在我的项目中压根就没看见有过这个属性,所以排除之。

结束语:折腾了一天结果还是没搞明白到底是什么原因,我也不想上论坛发帖子去问,因为这种帖子一发就铁定石沉大海了,就算有人回复那也是以灌水回复捞积分的居多。说句实话,百度知道上面真正懂技术的人是少之又少,大部分问题的回答都是牛头不对马嘴,完全不看问题问的是什么就在那边乱回答,参考意义实在是不大

操作环境:Win8.1企业版+VMWare WorkStation 12 Pro

电脑系统重装后,神马驱动都没了,包括adb的。现在做开发需要安装adb驱动,但是又不想在自己的电脑上安装那些360手机助手等等奇葩流氓软件,于是在虚拟机里面操作安装了adb驱动(死也是死个虚拟机而已)。问题来了,如何把这个驱动从虚拟机里面捞出来呢?现在知道的是驱动肯定在Windows文件夹中,为了方便,直接把Windows文件夹捞出来

尝试1:VMWare 有映射虚拟磁盘的功能,能轻松的把虚拟磁盘映射到主机中。

QQ20150927100732

但是!这有个问题。。。虽然磁盘映射成功了,在Windows资源管理器中能看见这个盘,但在Windows磁盘管理中却看不见这个盘;同理更新驱动的时候都提示位置不存在:

QQ20150927101109

QQ20150927101309

坑爹啊!

那么既然Windows资源管理器里面能看见它,就直接复制出来吧!

提示要提供权限

QQ20150927101513

然后,奇怪的一幕再次发生:

QQ20150927101618

MD居然说位置不可用!微软这是傻逼了吗???

右键修改文件夹属性:

QQ20150927101954

权限也改不了,真是哔了狗了。。。

换个思路:右键以管理员身份运行VMWare,这个主意看上去不错

QQ20150927102300

点击确定后,弹了一个对话框(大概是讲什么快照啊什么问题),再点了下确定

QQ20150927102444

还是位置不可用!这回在windows资源管理器里面都看不见了!

到此为止,这条路走不通。。。

尝试2:以前玩过M$的vhd,这种类型的盘挂载后能在Windows资源管理器里面显示,磁盘管理里面也能处理。google了一下找到这么个软件

QQ20150927102755

能把vmdk转成vhd。。。(不得不赞叹现在的软件真强大)

QQ20150927102929

双击转换完成后的vhd文件直接挂载,这次挂载在H盘

然后更新驱动程序:

QQ20150927103108

成功读取到了!

写到这里,基本上是实现我的想法了。虽然最后还是驱动安装失败,至少是发现了VMware的这个缺点,以后能少走弯路。。。