Android开发 人民币符号(¥)显示不一致的问题

不小心踩了个坑,发现这个人民币符号在不同机器上显示不一致,有的显示一横,有的显示两横。

百度查了一下,找到好很多解决办法,改字体,用图片等等。

最后发现原来用的是全角的“¥”的原因,全角的“¥”会受系统的影响。

而半角的“¥”则基本不受影响,在大部分机器上应该显示是一致的。

所以,今后请尽量用半角的人民币符号,这就是它(直接复制过去就行):¥

————————————————

原文链接:https://blog.csdn.net/admans/article/details/80939420

Android获取应用签名(开发版SHA1和发布版SHA1)

原文链接:https://blog.csdn.net/ShenQiXiaYang/article/details/83416232

当我们需要接入百度地图等一系列需要开发版SHA1和发布版SHA1才能创建完成应用的时候,如果找不到开发版SHA1和发布版SHA1是不是很苦恼,所以我们今天来快速查找开发版SHA1和发布版SHA1。
首先是开发版SHA1的获取,打开Android Studio,左上角偏下位置。
QQ图片20191018085552.png
点击Gradle,出现如图的页面:
QQ图片20191018085603.png
选择点击signingReport,出现下图所示的页面:
QQ图片20191018085607.png
SHA1: D8:84:F1:E1:BF:28:D9:CF:FC:AF:ED:84:3B:3D:F9:94:F0:85:E4:AD
这个就是我们的开发版SHA1。

那我们的发布版SHA1是什么呢?首先我们要在某应用市场发布我们的App的时候,需要对App进行签名,那么签名的时候就需要.jks文件。
那我的.jks文件是什么呢?如下图所示:
QQ图片20191018085616.png
有了这个.jks文件,那我们如何获取到发布版的SHA1呢?

第一种方法是使用AS获取:
看看我们的Android Studio的最底部的底部选项卡。(右下角,如下图所示:)
QQ图片20191018085620.png
点击打开倒数第二个选项卡,Terminal。出现如下图所示的页面:
QQ图片20191018085624.png
我们输入命令行keytool -list -v -keystore F:\yang.jks,出现如下图所示的页面:
QQ图片20191018085627.png
然后输入我们密钥库的口令(密钥库的口令就是我们的.jks文件的password)
键入我们的密钥库口令,然后就可以得到我们的发布版的SHA1了。如下图所示:
QQ图片20191018085630.png
可以看到我们的发布版SHA1是
SHA1: 02:6B:07:04:0F:CC:81:EE:15:7C:2B:3B:EE:F6:9A:9E:5A:D0:C0:33。

第二种方法是使用cmd获取:
QQ图片20191018085634.png
键入我们的密钥库口令。结果如下图所示:
QQ图片20191018085637.png
从上图中,可以看到我们的发布版的SHA1。

如此,本篇文章结束。

USB调试不能弹出授权窗口 unauthorized 的解决办法

在首次使用adb connect,然后adb shell的时候,常常需要点击弹出的对话框,否则出现

error: device unauthorized. Please check the confirmation dialog on your device.
这种情况在没有显示屏的时候或者多人连接时不太方便。这时候想默认授权而不用点击对话框想要去除弹框。
先了解它的工作原理,以下来自
-------------------------------------以下为转载--------------------------------------------------------------------------------------------
http://blog.csdn.net/sowhat_ah/article/details/43307907

工作原理是什么?

原来在我们的PC机(以windows为例)上启动了adb.exe进程时,adb会在本地生成一对密钥adbkey(私钥)与adbkey.pub(公钥);

根据弹框提示“The computer's RSA key fingerprint is:xxxx”,可以看出是一对RSA算法的密钥,其中公钥是用来发送给手机的;

当你执行“adb shell”时,adb.exe会将当前PC的公钥(或者公钥的hash值)(fingerprint)发送给android设备;这时,如果android上已经保存了这台PC的公钥,则匹配出对应的公钥进行认证,建立adb连接;如果android上没有保存这台PC的公钥,则会弹出提示框,让你确认是否允许这台机器进行adb连接,当你点击了允许授权之后,android就会保存了这台PC的adbkey.pub(公钥);

当然手机厂商也有可能会内置一些adbkey.pub(公钥);

那么问题来了,这些密钥在PC与Android上分别存储在哪里?

首先PC上,以Windows7为例,当你首次启动adb.exe时,会在C盘的当前用户的目录下生成一个".android"目录,其中adbkey与adbkey.pub就在这个目录下;(adb.exe会在启动时读取这两个文件(没有就重新生成),所以如果你要是删除或者修改了这两个文件之后,必须要关闭adb.exe进程,重启之后才能生效;)

其次Android上,PC的公钥被保存在一个文件中"/data/misc/adb/adb_keys";

在知道了adb这种认证的原理之后,你可以在不希望自己android设备授权任何PC设备进行adb链接时,清除"/data/misc/adb/adb_keys"文件;

也可以在没有屏幕的情况下,让已经认证过的PC将你PC上的adbkey.pub中的公钥导入到android中的"/data/misc/adb/adb_keys"文件中,或者将已经认证过的PC机上的adbkey与adbkey.pub拷贝到本机上覆盖你自己的adbkey与adbkey.pub,然后重启adb.exe,即可执行adb命令;

-------------------------------------------------------以上为转载---------------------------------------------------------------------------------------------------------------

因此,方法一、 根据转载的文章。在机器上建立/data/misc/adb/adb_keys 以及 在PC上建立adbkey.pub。

方法二、修改framework的代码,这里重点要说的方法,经过实验成功。

修改文件 UsbDebuggingActivity.java

  @Override
    public void onReceive(Context content, Intent intent) {
        String action = intent.getAction();
        if (!UsbManager.ACTION_USB_STATE.equals(action)) {
            return;
        }


        //: usb show UI
        //boolean connected = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false);
        boolean connected  = false;   //给connect赋值,关掉UI
        if (!connected) {
            mActivity.finish();
        }
   //allowUsbDebugging
   try {
   IBinder b = ServiceManager.getService(USB_SERVICE);     
      IUsbManager service = IUsbManager.Stub.asInterface(b);
   service.allowUsbDebugging(true, mKey);
        } catch (Exception e) {
        Log.e(TAG, "Unable to notify Usb service", e);
    }
   //<<end

    }
}

关于webview上传图片的坑

项目中遇到了需要在webview上传图片的需求,搜索了一把,找到几个可行的方法,同时也踩了个webview的坑,总结一下

我找到的是这样的方法

***首先 重写WebChromeClient 添加openFileChooser 方法

   // For Android 3.0+
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {//最终调用的都是这个
if (mUploadMessage != null) return;//坑就在这里 看后边注释
mUploadMessage = uploadMsg;
selectImage();
}

// For Android < 3.0
public void openFileChooser(ValueCallback<Uri> uploadMsg) {
openFileChooser(uploadMsg, "");
}

// For Android > 4.1.1
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
openFileChooser(uploadMsg, acceptType);
}



*** 然后自己实现selectImage()方法

```
private void selectImage() {//模仿IOS的弹出框
List<map <String, String>> list = new ArrayList<>();
HashMap<string , String> ch1 = new HashMap<>();
HashMap</string><string , String> ch2 = new HashMap<>();
HashMap</string><string , String> ch3 = new HashMap<>();
ch1.put("key", "从相册选择");
ch2.put("key", "拍照上传");
ch3.put("key", "取消");

<pre><code> list.add(ch1);
list.add(ch2);
list.add(ch3);
ListAdapter ad = new SimpleAdapter(this, list, R.layout.my_simple_list_item_1, new String[]{"key"}, new int[]{android.R.id.text1});
chosePicDialog = new AlertDialog.Builder(this).setAdapter(ad, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
switch (i) {
case 0:
getImageFromAlbum();

break;
case 1:
getImageFromCamera();

break;
case 2:
mUploadMessage.onReceiveValue(null);//这里是坑,如果取消了 不调用这句mUploadMessage.onReceiveValue()的话 整个webview就都没有响应了
mUploadMessage = null;//还有这里 上边已标出
break;
}

}
}).setCancelable(false).create();
chosePicDialog.getWindow().setGravity(Gravity.BOTTOM);
chosePicDialog.show();
}
</code></pre>

```

然后分别实现 从图库选择和拍照上传的方法

```
/**
* 调用相册
<em>/
protected void getImageFromAlbum() {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/</em>");//相片类型
startActivityForResult(intent, REQUEST_CODE_PICK_IMAGE);
}

<pre><code>/**
* 调用相机
*/
protected void getImageFromCamera() {//这里采用的是获取拍照原图的方法
String state = Environment.getExternalStorageState();
if (state.equals(Environment.MEDIA_MOUNTED)) {
File f = FileUtil.getNewPicFilePath();
Uri u = Uri.fromFile(f);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, u);
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
startActivityForResult(intent,REQUEST_CODE_CAPTURE_CAMEIA);
} else {
Toast.makeText(getApplicationContext(), "请确认已经插入SD卡", Toast.LENGTH_LONG).show();
}
}
</code></pre>

```
***FileUtil.class内容

```
public class FileUtil {
private static String LastPicFilePath = null;

<pre><code>public static File getNewPicFilePath() {
String dirStr = Environment.getExternalStorageDirectory().getPath() + "/DCIM/Camera/";

File dir = new File(dirStr);
if (!dir.exists()) {
dir.mkdirs();
}
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
String nowTime = format.format(new Date());
String localTempFileName = nowTime + ".jpg";
File f = new File(dir, localTempFileName);
setLastPicFilePath(f.getPath());
Log.e("getLastPicFilePath",getLastPicFilePath());
return f;
}

public static String getLastPicFilePath() {
return LastPicFilePath;
}

public static void setLastPicFilePath(String lastPicFilePath) {
LastPicFilePath = lastPicFilePath;
}
</code></pre>

}
```
***再重写onActivityResult

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != RESULT_OK) {
mUploadMessage.onReceiveValue(null);//这里防止拍照的时候取消了回来webview无响应的问题,这里是大坑
mUploadMessage = null;//上边注释说了,这里是坑
mWebView.requestFocus();
return;
}
if (requestCode == REQUEST_CODE_PICK_IMAGE) {
Uri uri = data.getData();
//to do find the path of pic by uri
mUploadMessage.onReceiveValue(uri);
} else if (requestCode == REQUEST_CODE_CAPTURE_CAMEIA) {
Uri uri = Uri.parse(FileUtil.getLastPicFilePath());//从上边指定的地址生成uri
mUploadMessage.onReceiveValue(uri);
}
super.onActivityResult(requestCode, resultCode, data);
}


总结



总体来说最坑的就是这个 mUploadMessage.onReceiveValue( );方法
没看WebChromeClient源码 猜想是如果不回调这句的话webview会一直等着你操作,造成整个webview界面没有响应,这个问题让我纠结了一下午时间,总结出来,希望对其他人有帮助。