From 0b8c5205efc41939c23980757354fef73f60fb57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=91=A3=E5=AE=8F=E5=AE=87?= Date: Tue, 22 Dec 2020 13:00:48 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BA=86=E5=B0=8F=E5=9C=B0?= =?UTF-8?q?=E5=9B=BE=E8=87=AA=E5=AE=9A=E4=B9=89=E6=A0=B7=E5=BC=8F=E6=B2=A1?= =?UTF-8?q?=E6=9C=89=E7=94=9F=E6=95=88=E7=9A=84bug=EF=BC=8C=E5=8E=9F?= =?UTF-8?q?=E5=9B=A0=E6=98=AF=E9=AB=98=E5=BE=B7=E5=9C=B0=E5=9B=BE=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98=EF=BC=8C=E8=A7=A3=E5=86=B3=E6=96=B9=E6=A1=88?= =?UTF-8?q?=E5=A6=82=E4=B8=8B=20=20aMap.setOnMapLoadedListener(new=20AMap.?= =?UTF-8?q?OnMapLoadedListener()=20{?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @Override public void onMapLoaded() { //Log.w("onMapLoaded", "===onMapLoaded===="); // 高德地图有bug,所以需要多次调用设置皮肤才能成功 if (options != null) { options.setCustomMapStylePath(styleFilePath); mAMapNaviView.setViewOptions(options); } //设置希望展示的地图缩放级别 CameraUpdate cameraUpdate = CameraUpdateFactory.zoomTo(12); aMap.moveCamera(cameraUpdate); } }); --- .../main/java/com/mogo/utils/FileUtils.java | 313 +++++++++++++----- .../src/main/assets/style.data | Bin 0 -> 141822 bytes .../src/main/assets/style_extra.data | Bin 0 -> 3118 bytes .../small/map/SmallMapDirectionView.java | 114 +++++-- .../module/small/map/SmallVisionProvider.java | 3 + 5 files changed, 319 insertions(+), 111 deletions(-) create mode 100644 modules/mogo-module-smp/src/main/assets/style.data create mode 100644 modules/mogo-module-smp/src/main/assets/style_extra.data diff --git a/foudations/mogo-utils/src/main/java/com/mogo/utils/FileUtils.java b/foudations/mogo-utils/src/main/java/com/mogo/utils/FileUtils.java index e7067de16b..aaa6e699ee 100644 --- a/foudations/mogo-utils/src/main/java/com/mogo/utils/FileUtils.java +++ b/foudations/mogo-utils/src/main/java/com/mogo/utils/FileUtils.java @@ -5,7 +5,9 @@ import android.content.Context; import android.net.Uri; import android.text.TextUtils; import android.util.Base64; +import android.util.Log; +import androidx.annotation.IntRange; import androidx.core.content.FileProvider; import java.io.BufferedInputStream; @@ -20,98 +22,100 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStreamWriter; - +/** + * 文件工具类 + */ public class FileUtils { - public static boolean createFileDir( String fileDir ) { + public static boolean createFileDir(String fileDir) { - if ( TextUtils.isEmpty( fileDir ) ) { + if (TextUtils.isEmpty(fileDir)) { return false; } try { - File dir = new File( fileDir ); + File dir = new File(fileDir); return dir.exists() || dir.mkdir(); - } catch ( Exception e ) { + } catch (Exception e) { return false; } } - public static boolean createFileDir( File dir ) { - if ( dir == null ) { + public static boolean createFileDir(File dir) { + if (dir == null) { return false; } try { return dir.exists() || dir.mkdir(); - } catch ( Exception e ) { + } catch (Exception e) { return false; } } - public static void writeToFile( String fileDir, String fileName, String content ) { - if ( fileDir == null || fileName == null || content == null ) { + public static void writeToFile(String fileDir, String fileName, String content) { + if (fileDir == null || fileName == null || content == null) { return; } - if ( !createFileDir( fileDir ) ) { + if (!createFileDir(fileDir)) { return; } FileOutputStream fos = null; OutputStreamWriter osw = null; try { - fos = new FileOutputStream( fileDir + fileName, true ); - osw = new OutputStreamWriter( fos ); - osw.write( content ); + fos = new FileOutputStream(fileDir + fileName, true); + osw = new OutputStreamWriter(fos); + osw.write(content); osw.flush(); - } catch ( IOException e ) { + } catch (IOException e) { e.printStackTrace(); } finally { - IOUtils.closeSilently( fos ); - IOUtils.closeSilently( osw ); + IOUtils.closeSilently(fos); + IOUtils.closeSilently(osw); } } /** * Read a text file into a String, optionally limiting the length. */ - public static String readTextFile( File file ) { + public static String readTextFile(File file) { InputStream is = null; BufferedInputStream bis = null; ByteArrayOutputStream bos = null; String text = null; try { - is = new FileInputStream( file ); - bis = new BufferedInputStream( is ); + is = new FileInputStream(file); + bis = new BufferedInputStream(is); bos = new ByteArrayOutputStream(); int len; byte[] data = new byte[1024]; do { - len = bis.read( data ); - if ( len > 0 ) bos.write( data, 0, len ); - } while ( len == data.length ); + len = bis.read(data); + if (len > 0) bos.write(data, 0, len); + } while (len == data.length); text = bos.toString(); - } catch ( Exception e ) { + } catch (Exception e) { e.printStackTrace(); } finally { - IOUtils.closeSilently( is ); - IOUtils.closeSilently( bis ); - IOUtils.closeSilently( bos ); + IOUtils.closeSilently(is); + IOUtils.closeSilently(bis); + IOUtils.closeSilently(bos); } return text; } - public static String fileToBase64( File file ) { + public static String fileToBase64(File file) { String base64 = null; InputStream in = null; try { - in = new FileInputStream( file ); + in = new FileInputStream(file); byte[] bytes = new byte[in.available()]; - int length = in.read( bytes ); - base64 = Base64.encodeToString( bytes, 0, length, Base64.DEFAULT ); - } catch ( FileNotFoundException e ) { + int length = in.read(bytes); + base64 = Base64.encodeToString(bytes, 0, length, Base64.DEFAULT); + } catch (FileNotFoundException e) { e.printStackTrace(); - } catch ( IOException e ) { + } catch (IOException e) { e.printStackTrace(); } finally { - IOUtils.closeSilently( in ); + IOUtils.closeSilently(in); } return base64; } @@ -119,81 +123,81 @@ public class FileUtils { /** * Writes string to file. Basically same as "echo -n $string > $filename" */ - public static void stringToFile( String filename, String string ) { + public static void stringToFile(String filename, String string) { FileWriter out = null; try { - out = new FileWriter( filename ); - out.write( string ); - } catch ( Exception e ) { + out = new FileWriter(filename); + out.write(string); + } catch (Exception e) { e.printStackTrace(); } finally { - IOUtils.closeSilently( out ); + IOUtils.closeSilently(out); } } - public static InputStream stringToStream( String content ) { + public static InputStream stringToStream(String content) { InputStream inputStream = null; try { - inputStream = new ByteArrayInputStream( content.getBytes() ); - } catch ( Exception e ) { + inputStream = new ByteArrayInputStream(content.getBytes()); + } catch (Exception e) { e.printStackTrace(); } return inputStream; } - public static String streamToString( InputStream is ) throws IOException { + public static String streamToString(InputStream is) throws IOException { String content = null; try { ByteArrayOutputStream bos = new ByteArrayOutputStream(); int i = -1; - while ( ( i = is.read() ) != -1 ) { - bos.write( i ); + while ((i = is.read()) != -1) { + bos.write(i); } content = bos.toString(); - } catch ( Exception e ) { + } catch (Exception e) { e.printStackTrace(); } return content; } - public static String getStringFromFile( Context context, String fileName ) { + public static String getStringFromFile(Context context, String fileName) { FileInputStream fis = null; ByteArrayOutputStream os = null; String content = null; try { - fis = context.openFileInput( fileName ); + fis = context.openFileInput(fileName); os = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int length = -1; - while ( ( length = fis.read( buffer ) ) != -1 ) { - os.write( buffer, 0, length ); + while ((length = fis.read(buffer)) != -1) { + os.write(buffer, 0, length); } content = os.toString(); - } catch ( Exception e ) { + } catch (Exception e) { e.printStackTrace(); } finally { - IOUtils.closeSilently( fis ); - IOUtils.closeSilently( os ); + IOUtils.closeSilently(fis); + IOUtils.closeSilently(os); } return content; } - public static InputStream getStreamFromFile( Context context, String fileName ) { + public static InputStream getStreamFromFile(Context context, String fileName) { FileInputStream fis = null; try { - fis = context.openFileInput( fileName ); - } catch ( Exception e ) { + fis = context.openFileInput(fileName); + } catch (Exception e) { e.printStackTrace(); } return fis; } - public static void saveStringToFile( Context context, String content, String fileName ) { + public static void saveStringToFile(Context context, String content, String fileName) { try { - FileOutputStream fos = context.openFileOutput( fileName, Context.MODE_PRIVATE ); - fos.write( content.getBytes() ); - IOUtils.closeSilently( fos ); - } catch ( Exception e ) { + FileOutputStream fos = context.openFileOutput(fileName, Context.MODE_PRIVATE); + fos.write(content.getBytes()); + IOUtils.closeSilently(fos); + } catch (Exception e) { e.printStackTrace(); } } @@ -201,10 +205,10 @@ public class FileUtils { /** * 将scheme为file的uri转成FileProvider 提供的content uri */ - public static Uri convertFileUriToFileProviderUri( Context context, Uri uri ) { - if ( uri == null ) return null; - if ( ContentResolver.SCHEME_FILE.equals( uri.getScheme() ) ) { - return getUriForFile( context, new File( uri.getPath() ) ); + public static Uri convertFileUriToFileProviderUri(Context context, Uri uri) { + if (uri == null) return null; + if (ContentResolver.SCHEME_FILE.equals(uri.getScheme())) { + return getUriForFile(context, new File(uri.getPath())); } return uri; @@ -213,38 +217,195 @@ public class FileUtils { /** * 创建一个用于拍照图片输出路径的Uri (FileProvider) */ - public static Uri getUriForFile( Context context, File file ) { - return FileProvider.getUriForFile( context, getFileProviderName( context ), file ); + public static Uri getUriForFile(Context context, File file) { + return FileProvider.getUriForFile(context, getFileProviderName(context), file); } - public static String getFileProviderName( Context context ) { + public static String getFileProviderName(Context context) { return context.getPackageName() + ".fileprovider"; } /** * 把Uri 解析出文件绝对路径 */ - public static String parseOwnUri( Context context, Uri uri ) { - if ( uri == null ) return null; + public static String parseOwnUri(Context context, Uri uri) { + if (uri == null) return null; String path; - if ( TextUtils.equals( uri.getAuthority(), getFileProviderName( context ) ) ) { - path = new File( uri.getPath() ).getAbsolutePath(); + if (TextUtils.equals(uri.getAuthority(), getFileProviderName(context))) { + path = new File(uri.getPath()).getAbsolutePath(); } else { path = uri.getPath(); } return path; } - public static String getFileStreamPath( Context context, String name ) { + public static String getFileStreamPath(Context context, String name) { String absFileName = null; try { - File file = context.getFileStreamPath( name ); - if ( file != null && file.exists() ) { + File file = context.getFileStreamPath(name); + if (file != null && file.exists()) { absFileName = file.getAbsolutePath(); } - } catch ( Exception e ) { + } catch (Exception e) { e.printStackTrace(); } return absFileName; } + + + /** + * 拷贝文件数据到指定目录 + * + * @param is + * @param to + * @param listener + */ + public static void copy(final InputStream is, final String to, final FileCopyListener listener) { + new Thread(new Runnable() { + @Override + public void run() { + Log.w("FileUtils", "======copy======"); + + if (listener != null) { + listener.onStart(); + } + + try { + + long fileSize = is.available(); + long process = 0; + + byte[] buff = new byte[1024]; + int rc = 0; + + File toFile = new File(to); + if (!toFile.getParentFile().exists()) { + toFile.getParentFile().mkdirs(); + } + + FileOutputStream fos = new FileOutputStream(toFile); + + while ((rc = is.read(buff, 0, 1024)) > 0) { + process += rc; + fos.write(buff, 0, rc); + if (listener != null) { + listener.onProcess(((int) (((float) process) * 100 / fileSize))); + } + } + + fos.flush(); + fos.close(); + is.close(); + + } catch (Exception e) { + if (listener != null) { + listener.onFail(e); + return; + } + } + + if (listener != null) { + listener.onFinish(to); + } + } + }).start(); + } + + /** + * 拷贝文件到制定目录 + * + * @param from + * @param to + * @param listener + */ + public static void copy(final String from, final String to, final FileCopyListener listener) { + new Thread(new Runnable() { + @Override + public void run() { + File file = null; + try { + file = new File(from); + } catch (Exception e) { + if (listener != null) { + listener.onFail(e); + } + return; + } + if (!file.isFile()) { + if (listener != null) { + listener.onFail(new Exception(String.format("%s is not a file", from))); + return; + } + } + if (!file.exists()) { + if (listener != null) { + listener.onFail(new FileNotFoundException(String.format("%s is not exists.", from))); + return; + } + } + + if (listener != null) { + listener.onStart(); + } + + long fileSize = file.length(); + long process = 0; + + try { + FileInputStream fis = new FileInputStream(file); + + byte[] buff = new byte[1024]; + int rc = 0; + + File toFile = new File(to); + if (!toFile.getParentFile().exists()) { + toFile.getParentFile().mkdirs(); + } + + FileOutputStream fos = new FileOutputStream(toFile); + + while ((rc = fis.read(buff, 0, 1024)) > 0) { + process += rc; + fos.write(buff, 0, rc); + if (listener != null) { + listener.onProcess(((int) (((float) process) * 100 / fileSize))); + } + } + + fos.flush(); + fos.close(); + fis.close(); + + } catch (Exception e) { + if (listener != null) { + listener.onFail(e); + return; + } + } + + if (listener != null) { + listener.onFinish(to); + } + } + }).start(); + } + + + /** + * 文件拷贝监听 + */ + public interface FileCopyListener { + // 开始 + void onStart(); + + // 失败 + void onFail(Exception e); + + // 进度 + void onProcess(@IntRange(from = 0, to = 100) int process); + + // 结束成功 + void onFinish(String toPath); + } + } diff --git a/modules/mogo-module-smp/src/main/assets/style.data b/modules/mogo-module-smp/src/main/assets/style.data new file mode 100644 index 0000000000000000000000000000000000000000..412a2ab911461b5fab38b7083914ac978c20bd0e GIT binary patch literal 141822 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