安卓开发问题汇总
Unexpected lock protocol found in lock file. Expected 3, found 37.
错误描述
在项目构建时报错:Unexpected lock protocol found in lock file. Expected 3, found 37.
原因
通常是Android Studio或电脑意外关闭引起的,具体原理未知。
解决方法
删除C盘用户目录下的.gradle文件,重启Android Studio。
TextView解决中英文混排自动换行
解决办法:自定义TextView解决中英文混排自动换行
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.widget.TextView;
/**
*
*/
public class JustifyTextView extends TextView {
private int mLineY;
private int mViewWidth;
public static final String TWO_CHINESE_BLANK = " ";
public JustifyTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
super.onLayout(changed, left, top, right, bottom);
}
@Override
protected void onDraw(Canvas canvas) {
TextPaint paint = getPaint();
paint.setColor(getCurrentTextColor());
paint.drawableState = getDrawableState();
mViewWidth = getMeasuredWidth();
String text = getText().toString();
mLineY = 0;
mLineY += getTextSize();
Layout layout = getLayout();
// layout.getLayout()在4.4.3出现NullPointerException
if (layout == null) {
return;
}
Paint.FontMetrics fm = paint.getFontMetrics();
int textHeight = (int) (Math.ceil(fm.descent - fm.ascent));
textHeight = (int) (textHeight * layout.getSpacingMultiplier() + layout
.getSpacingAdd());
//解决了最后一行文字间距过大的问题
for (int i = 0; i < layout.getLineCount(); i++) {
int lineStart = layout.getLineStart(i);
int lineEnd = layout.getLineEnd(i);
float width = StaticLayout.getDesiredWidth(text, lineStart,
lineEnd, getPaint());
String line = text.substring(lineStart, lineEnd);
if(i < layout.getLineCount() - 1) {
if (needScale(line)) {
drawScaledText(canvas, lineStart, line, width);
} else {
canvas.drawText(line, 0, mLineY, paint);
}
} else {
canvas.drawText(line, 0, mLineY, paint);
}
mLineY += textHeight;
}
}
private void drawScaledText(Canvas canvas, int lineStart, String line,
float lineWidth) {
float x = 0;
if (isFirstLineOfParagraph(lineStart, line)) {
String blanks = " ";
canvas.drawText(blanks, x, mLineY, getPaint());
float bw = StaticLayout.getDesiredWidth(blanks, getPaint());
x += bw;
line = line.substring(3);
}
int gapCount = line.length() - 1;
int i = 0;
if (line.length() > 2 && line.charAt(0) == 12288
&& line.charAt(1) == 12288) {
String substring = line.substring(0, 2);
float cw = StaticLayout.getDesiredWidth(substring, getPaint());
canvas.drawText(substring, x, mLineY, getPaint());
x += cw;
i += 2;
}
float d = (mViewWidth - lineWidth) / gapCount;
for (; i < line.length(); i++) {
String c = String.valueOf(line.charAt(i));
float cw = StaticLayout.getDesiredWidth(c, getPaint());
canvas.drawText(c, x, mLineY, getPaint());
x += cw + d;
}
}
private boolean isFirstLineOfParagraph(int lineStart, String line) {
return line.length() > 3 && line.charAt(0) == ' '
&& line.charAt(1) == ' ';
}
private boolean needScale(String line) {
if (line == null || line.length() == 0) {
return false;
} else {
return line.charAt(line.length() - 1) != '\n';
}
}
}
使用
<com.hxtx.august.tools.JustifyTextView
android:id="@+id/tv_fm_ftp_path"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:layout_marginStart="15dp"
android:layout_marginEnd="15dp"
android:text="路径:"
android:textSize="15sp"
tools:ignore="RtlSymmetry" />
listview的item的点击事件与checkbox点击时间冲突
设置checkbox属性
android:focusable="false" //因为checkBox的点击事件优先级高于listview的点击事件
<CheckBox
android:id="@+id/cb_folder_content_checkBox"
android:button="@null"
android:layout_width="24dp"
android:layout_height="24dp"
android:focusable="false"
android:background="@drawable/check_style"
/>
APP本地下载文件出错
java.lang.RuntimeException: java.nio.file.NoSuchFileException: /data/user/0/com.hxtx.august/files/FTPData/README.md
这是因为没有找到这个路径和文件,应该判断一下有没有这个文件夹
File localFolder = new File(androidAppUrl + "/FTPData");
if (!localFolder.exists()) {
localFolder.mkdirs();
}
开子线程
// 需要执行一个方法
private void FtpDown(){
// 开启一个子线程,进行网络操作,等待有返回结果,使用handler通知UI
new Thread(networkTask).start();
}
// 在线程中写逻辑
Runnable networkTask = new Runnable() {
@Override
public void run() {
try {
String download = FileUtils.GetFtpPath(FtpActivity.this);
downloadTv.setText("下载中...");
// 回调成功
Message msg = Message.obtain();
msg.what = 1;
msg.obj = e;
handler.sendMessage(msg);
// 如果传递数据可以这么写,result 是一个数据(对象或者列表)
Message message = handler.obtainMessage(0x001, fileContent);
handler.sendMessage(message);
}catch (Exception e){
// 回调失败
Log.e(TAG,"出现异常----->>"+e.getMessage());
Message msg = Message.obtain();
msg.what = 1;
msg.obj = e.getMessage();
handler.sendMessage(msg);
// 也可以这么写
handler.sendEmptyMessage(0x002);
}
}
}
//用来接收子线程回调的结果
Handler handler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
// 如果传递的是数据,则需要这么解析
List<String> fileContent = (List<String>) msg.obj;
switch (msg.what) {
case 1://异常
String error = (String) msg.obj;
downloadTv.setText("出现异常-->"+error);
break;
case 2://成功
String result = (String) msg.obj;
downloadTv.setText(result);
break;
}
}
};
页面跳转并传递数据
传递字符串
发送页面
Intent TestWifiIntent = new Intent(FtpManageAction.this, SinglePageAction.class);
TestWifiIntent.putExtra("UrlData","file:///storage/emulated/0/Download/sample.csv");
startActivity(TestWifiIntent);
接受页面
Intent intent = getIntent();//获取intent对象
String csvFilePath = intent.getStringExtra("UrlData");
当路径包含中文时,FTP读取FTP服务器列表出问题
解决办法:将路径转换为ISO-8859-1编码
String isoPath = new String(path.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
FTPFile[] files = ftpClient.listFiles(isoPath);
读取FTP内容,带进度
// 进度
long step = ftpFile.getSize() / 100;
long process = 0;
long currentSize = 0;
byte[] b = new byte[1024];
int length;
InputStream inputStream = ftpClient.retrieveFileStream(currentPath);
if(inputStream!=null){
while ((length = inputStream.read(b)) != -1) {
// 下载文件
buffOut.write(b, 0, length);
currentSize = currentSize + length;
if (currentSize / step != process) {
process = currentSize / step;
//每隔%5的进度返回一次
if (process % 5 == 0) {
Log.d("IVESTAG", "ftp文件正在下载: "+process);
}
}
}
Message msg = Message.obtain();
msg.what = 1;
msg.obj = localFolder;
handlerFTPDownloadSingleData.sendMessage(msg);
// 关闭文件流
buffOut.close();
inputStream.close();
// 此方法是来确保流处理完毕,如果没有此方法,可能会造成现程序死掉
// if (ftpClient.completePendingCommand()) {
// Log.d("IVESTAG", "1ftp文件下载成功: "+ new File(localPath));
// } else {
// Log.d("IVESTAG", "2ftp文件下载失败: ");
// }
} else {
Message msg = Message.obtain();
msg.what = 0;
msg.obj = "文件空,未读到数据";
handlerFTPDownloadSingleData.sendMessage(msg);
}
问题记录
open failed: EISDIR (Is a directory)
操作错误,这是一个文件夹而不是一个文件。
open failed: EEXIST (File exists)
安卓Android的Textview显示问题:一行没显示满就换行
设置Textview的属性android:breakStrategy为simple
<TextView
android:id="@+id/tv_folder_content_item_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:breakStrategy="simple"
android:text="文本框"
android:textSize="15sp"
/>
预览CSV文件
// 浏览器预览
Intent TestWifiIntent = new Intent(FtpManageAction.this, SinglePageAction.class);
TestWifiIntent.putExtra("UrlData",localFile);
startActivity(TestWifiIntent);
// WPS预览
Uri file = FileProvider.getUriForFile(FtpManageAction.this, "com.hxtx.august.fileprovider", localFile);
Intent intent = new Intent();
List<ResolveInfo> resInfoList = getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolveInfo : resInfoList) {
String packageName = resolveInfo.activityInfo.packageName;
grantUriPermission(packageName, file, Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
intent.setAction(Intent.ACTION_VIEW);
String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(MimeTypeMap.getFileExtensionFromUrl(file.toString()));
intent.setDataAndType(file, mimeType);
startActivity(intent);
数据类型转换
// 字符串转换为长整型(long)
String str = "12345";
long num = Long.parseLong(str);
System.out.println(num);
// 字符串转换为长整型(long)
String str = "12345";
long num = Long.parseLong(str);
System.out.println(num);
// 字符串分割
String str = "apple/banana/cherry";
String[] parts = str.split("/");
for (String part : parts){
System.out.println(part);
}