广告位联系
返回顶部
分享到

Android封装常用工具类的介绍

Android 来源:互联网 作者:佚名 发布时间:2024-03-25 22:13:36 人浏览
摘要

日志封装类-MyLog 是对androidlog的封装,封装后 可以设置显示级别 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58

日志封装类-MyLog

是对android log的封装,封装后 可以设置显示级别

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

/**

 * Log的封装类,方便开启和关闭log

 */

public class MyLog {

    public static final int VERBOSE = 1;

    public static final int DEBUG = 2;

    public static final int INFO = 3;

    public static final int WARN = 4;

    public static final int ERROR = 5;

    public static final int NOTHING = 6;

    public static final int level = VERBOSE; //设置显示级别

    public static final String MYLOG_PATH_SDCARD_DIR = "/sdcard/ScanZbar/log";// 日志文件在sdcard中的路径

    public static final String MY_LOG_FILE_NAME = "Log.txt";// 本类输出的日志文件名称

 

 

    public static void v(String tag, String msg){

        if(level <= VERBOSE)

            Log.v(tag,msg);

    }

 

    public static void d(String tag, String msg){

        if(level <= DEBUG)

            Log.d(tag,msg);

    }

 

    public static void i(String tag, String msg){

        if(level <= INFO)

            Log.i(tag,msg);

    }

 

    public static void w(String tag, String msg){

        if(level <= WARN)

            Log.w(tag,msg);

    }

 

    public static void e(String tag, String msg){

        if(level <= ERROR)

            Log.e(tag,msg);

    }

 

    //调用该方法,可以将日志写入日志文件

    public static void Loge(String tag, String msg){

        if(LEVEL <= ERROR) {

            Log.e(tag, msg);

            writeLogtoFile("ERROR",tag,msg);

        }

    }

 

/**

     * 打开日志文件并写入日志

     * @param mylogtype

     * @param tag

     * @param text

     */

    private static void writeLogtoFile(String mylogtype, String tag, String text) {// 新建或打开日志文件

        Date nowtime = new Date();

        String needWriteFiel = new SimpleDateFormat(TimeUtil.SDF3).format(nowtime);

        String needWriteMessage = new SimpleDateFormat(TimeUtil.SDF1).format(nowtime) + " " + mylogtype + " " + tag + " " + text;

        File dirPath = Environment.getExternalStorageDirectory();

 

        File dirsFile = new File(MYLOG_PATH_SDCARD_DIR);

        if (!dirsFile.exists()){

            dirsFile.mkdirs();

        }

        //创建日志文件

        File file = new File(dirsFile.toString(), needWriteFiel +".txt");// MYLOG_PATH_SDCARD_DIR

        if (!file.exists()) {

            try {

                //在指定的文件夹中创建文件

                boolean creatB = file.createNewFile();

                if(!creatB)

                    MyLog.e("mylog","创建日志文件失败!");

            } catch (Exception e) {

                e.printStackTrace();

            }

        }

        try(FileWriter filerWriter = new FileWriter(file, true);// 后面这个参数代表是不是要接上文件中原来的数据,不进行覆盖

            BufferedWriter bufWriter = new BufferedWriter(filerWriter)) {

            bufWriter.write(needWriteMessage);

            bufWriter.newLine();

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

 

}

使用使用和正常log使用一样

1

2

3

MyLog.e("mylog","123");

MyLog.i("mylog","222");

...

线程封装类-LocalThreadPools

针对AsyncTask被弃用的替代

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

/**

 * @Description TODO(全局使用的线程池)

 */

public class LocalThreadPools {

    private static int threadNum = 0;

    private static String TAG = LocalThreadPools.class.getSimpleName();

 

    private static ExecutorService THREAD_POOL_EXECUTOR;

 

    /**

     * CPU数量

     */

    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();

    /**

     * 线程池数量

     */

    private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT-1,4));

    /**

     * 最大线程数量 = CPU数量*2+1

     */

    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2+1;

    /**

     * 等待线程存活时间

     */

    private static final int KEEP_ALIVE_SECONDS = 60;

    /**

     * 等待线程存活时间的单位

     */

    private static final TimeUnit unit = TimeUnit.MINUTES;

    private static final BlockingQueue<Runnable> sPoolWorkQueue = new LinkedBlockingQueue<>(8);

    /**

     * 线程工厂

     */

    private static final ThreadFactory sThreadFactory = new ThreadFactory() {

        private final AtomicInteger mCount = new AtomicInteger(1);

 

        public Thread newThread(Runnable r) {

            threadNum++;

            MyLog.e("mylog","线程工厂创建一个线程:"+threadNum+","+mCount.getAndIncrement());

            return new Thread(r, "MangoTask #" + mCount.getAndIncrement());

        }

    };

 

    private void initThreadPool() {

        MyLog.e("mylog","core_pool_size:"+CORE_POOL_SIZE+",maximum_pool_size:"+MAXIMUM_POOL_SIZE+"," +

                "KEEP_ALIVE_SECONDS:"+KEEP_ALIVE_SECONDS+",");

        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(

                CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, unit,

                sPoolWorkQueue, sThreadFactory,new RejectedHandler()){

            @Override

            public void execute(Runnable command) {

                super.execute(command);

                MyLog.e("mylog","-----------ActiveCount="+getActiveCount());

                MyLog.e("mylog","-----------PoolSize="+getPoolSize());

                MyLog.e("mylog","-----------Queue="+getQueue().size());

                MyLog.e("mylog","-----------finish="+getCompletedTaskCount());

            }

        };

        //允许核心线程空闲超时时被回收

        threadPoolExecutor.allowCoreThreadTimeOut(true);

        THREAD_POOL_EXECUTOR = threadPoolExecutor;

    }

 

    private class RejectedHandler implements RejectedExecutionHandler {

 

        @Override

        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {

            //可在这里做一些提示用户的操作

            Tools.showToast(mContext.get(),"当前执行的任务过多,请稍后再试");

        }

    }

 

    private WeakReference<Context> mContext;

    private static LocalThreadPools instance;

    private LocalThreadPools(Context context){

        mContext = new WeakReference<>(context);

        initThreadPool();

    }

    public static LocalThreadPools getInstance(Context context){

        if (instance == null) {

            instance = new LocalThreadPools(context);

        }

        return instance;

    }

 

    public void execute(Runnable command){

        THREAD_POOL_EXECUTOR.execute(command);

    }

 

 

    /**

     * 通过interrupt方法尝试停止正在执行的任务,但是不保证真的终止正在执行的任务

     * 停止队列中处于等待的任务的执行

     * 不再接收新的任务

     * @return 等待执行的任务列表

     */

    public static List<Runnable> shutdownNow(){

        return THREAD_POOL_EXECUTOR.shutdownNow();

    }

 

    /**

     * 停止队列中处于等待的任务

     * 不再接收新的任务

     * 已经执行的任务会继续执行

     * 如果任务已经执行完了没有必要再调用这个方法

     */

    public void shutDown(){

        THREAD_POOL_EXECUTOR.shutdown();

        sPoolWorkQueue.clear();

    }

 

}

使用

1

2

3

4

5

6

LocalThreadPools.getInstance((TestActivity) mView).execute(new Runnable() {

    @Override

    public void run() {

        //异步操作

    }           

});

自定义进度条-LoadProgressbar

自定义进度条

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

/**

 * 进度条

 */

public class DownLoadProgressbar extends View {

    private Paint paint = new Paint(); // 绘制背景灰色线条画笔

    private Paint paintText = new Paint(); // 绘制下载进度画笔

    private float offset = 0f; // 下载偏移量

    private float maxvalue = 0f; // 进度的总大小

    private float currentValue = 0f; // 当前进度

    private Rect mBound = new Rect(); // 获取百分比数字的长宽

    private String percentValue = "0%"; // 要显示的现在百分比

    private float offsetRight = 0f; // 灰色线条距离右边的距离

    private int textSize = SizeUtils.sp2px(25); // 百分比的文字大小

    private float offsetTop = SizeUtils.dp2px(18); // 距离顶部的偏移量

 

 

    public DownLoadProgressbar(Context context) {

        this(context, null);

    }

 

    public DownLoadProgressbar(Context context, @Nullable AttributeSet attrs) {

        this(context, attrs, 0);

    }

 

    public DownLoadProgressbar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {

        super(context, attrs, defStyleAttr);

        getTextWidth();

    }

 

 

    @Override

    protected void onDraw(Canvas canvas) {

        super.onDraw(canvas);

        // 绘制底色

        paint.setColor(Color.parseColor("#eeeeee"));

        paint.setStrokeWidth(SizeUtils.dp2px(10));

        canvas.drawLine(0, offsetTop, getWidth() - offsetRight, offsetTop, paint);

        // 绘制进度条颜色

        paint.setColor(Color.parseColor("#ff0000"));

        paint.setStrokeWidth(SizeUtils.dp2px(11));

        canvas.drawLine(0, offsetTop, offset, offsetTop, paint);

        paint.setColor(Color.parseColor("#ffffff"));

        paint.setStrokeWidth(SizeUtils.dp2px(1));

        paintText.setColor(Color.parseColor("#ffffff"));

        paintText.setTextSize(textSize);

        paintText.setAntiAlias(true);

        paintText.getTextBounds(percentValue, 0, percentValue.length(), mBound);

        canvas.drawLine(offset, offsetTop, offset + mBound.width() + SizeUtils.dp2px(4), offsetTop, paint);

        canvas.drawText(percentValue, offset, offsetTop + mBound.height() / 2 - SizeUtils.dp2px(2), paintText);

    }

 

    public void setCurrentValue(float currentValue) {

        this.currentValue = currentValue;

        int value = (int) (currentValue * 100 / maxvalue);

        if (value < 100 && value > 0) {

            percentValue = value + "%";

        } else if (value <= 0) {

            percentValue = "0%";

        } else {

            percentValue = "100%";

        }

        calc();

        invalidate();

    }

 

 

    private void calc() {

        if (currentValue < maxvalue) {

            offset = (getWidth() - offsetRight) * currentValue / maxvalue;

        } else {

            offset = getWidth() - offsetRight;

        }

    }

 

    /**

     * 设置最大值

     *

     * @param maxValue

     */

    public void setMaxvalue(int maxValue) {

        this.maxvalue = maxValue;

    }

 

    /**

     * 获取“100%”的宽度

     */

    public void getTextWidth() {

        Paint paint = new Paint();

        Rect rect = new Rect();

        paint.setTextSize(textSize);

        paint.setAntiAlias(true);

        paint.getTextBounds("100%", 0, "100%".length(), rect);

        offsetRight = rect.width() + SizeUtils.dp2px(5);;

    }

}

解压缩类-ZipUtils

解压缩

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

307

308

309

310

311

312

313

314

315

316

317

318

319

320

321

322

323

324

325

326

327

328

329

330

331

332

333

334

335

336

337

338

339

340

341

342

343

344

345

346

347

348

349

350

351

352

353

354

355

356

357

358

359

360

361

362

363

364

365

366

367

368

369

370

371

372

373

374

375

376

377

378

379

380

381

382

383

384

385

386

387

388

389

390

391

392

393

394

395

396

397

398

399

400

401

402

403

404

405

406

407

408

409

410

411

412

413

414

415

416

417

418

419

420

421

422

423

424

425

/**

 * 解压缩zip文件

 */

public class ZipUtils {

 

    public ZipUtils() {

    }

 

    /**

     * 根据byte数组,生成文件

     */

    public static void getFile(byte[] bfile, String filePath, String fileName) {

        BufferedOutputStream bos = null;

        FileOutputStream fos = null;

        File file = null;

        try {

            File dir = new File(filePath);

            if (!dir.exists()) {//判断文件目录是否存在

                dir.mkdirs();

            }

            file = new File(filePath + fileName);

            fos = new FileOutputStream(file);

            bos = new BufferedOutputStream(fos);

            bos.write(bfile);

        } catch (Exception e) {

            e.printStackTrace();

        } finally {

            if (bos != null) {

                try {

                    bos.close();

                } catch (IOException e1) {

                    e1.printStackTrace();

                }

            }

            if (fos != null) {

                try {

                    fos.close();

                } catch (IOException e1) {

                    e1.printStackTrace();

                }

            }

        }

    }

 

    //  使用密码解压(图片不加密)

    public static boolean unZipFile1(String zipFileFullName, String filePath, String password) {

        try {

            ZipFile zipFile = new ZipFile(zipFileFullName);

            // 如果解压需要密码

            if (zipFile.isEncrypted()) {

                zipFile.setPassword(password);

            }

            File file = new File(filePath);

            if (!file.getParentFile().exists()) {

                file.getParentFile().mkdirs();

            }

            zipFile.extractAll(filePath);//提取所有文件

            return true;

        } catch (Exception e) {

            e.printStackTrace();

            return false;

        }

    }

 

    //  使用密码解压

    public static boolean unZipFile(String zipFileFullName, String filePath, String password) {

        try {

            ZipFile zipFile = new ZipFile(zipFileFullName);

            // 如果解压需要密码

            if (zipFile.isEncrypted()) {

                zipFile.setPassword(password);

            }

            File file = new File(filePath);

            if (!file.getParentFile().exists()) {

                file.getParentFile().mkdirs();

            }

            zipFile.extractAll(filePath);//提取所有文件

//            压缩

            ZipFolder(filePath, filePath + "01");

//            解压

            ZipUtils.UnZipFolder(filePath + "01", filePath);

            return true;

        } catch (Exception e) {

            e.printStackTrace();

            return false;

        }

    }

 

    /**

     * 解压zip到指定的路径

     *

     * @param zipFileString ZIP的名称

     * @param outPathString 要解压缩路径

     * @throws Exception

     */

    public static void UnZipFolder(String zipFileString, String outPathString)  {

        ZipInputStream inZip = null;

        OutputStream out = null;

        try{

            inZip = new ZipInputStream(new FileInputStream(zipFileString));

            ZipEntry zipEntry;

            String szName = "";

            List<File> fileList = new ArrayList<File>();

            while ((zipEntry = inZip.getNextEntry()) != null) {

                szName = zipEntry.getName();

                if (zipEntry.isDirectory()) {

                    //获取部件的文件夹名

                    szName = szName.substring(0, szName.length() - 1);

                    File folder = new File(outPathString + File.separator + szName);

                    folder.mkdirs();

                } else {

                    File file = new File(outPathString + File.separator + szName);

                    if (!file.exists()) {

                        fileList.add(file);

                        file.getParentFile().mkdirs();

                        file.createNewFile();

                    }

                    // 获取文件的输出流

//                FileOutputStream out = new FileOutputStream(file);

                    out = AesUtil.encrypt(file, AesUtil.toKey(MyApplication.getInstance().getAESKey().getBytes()));// 加密

                    int len;

                    byte[] buffer = new byte[1024];

                    // 读取(字节)字节到缓冲区

                    while ((len = inZip.read(buffer)) != -1) {

                        // 从缓冲区(0)位置写入(字节)字节

                        out.write(buffer, 0, len);

                        out.flush();

                    }

                    out.close();

                }

            }

            inZip.close();

//        删除目录下多余文件夹

            File dirFile = new File(outPathString);

            File[] files = dirFile.listFiles();

            for (int i = 0; i < files.length; i++) {

                if (files[i].isDirectory()) {

                    deleteDirectory(files[i].getAbsolutePath());

                }

            }

        }catch (Exception e){

            e.printStackTrace();

        }finally {

            if(inZip != null){

                safeClose(inZip);

            }

            if(out != null){

                safeClose(out);

            }

        }

    }

    public static void safeClose(OutputStream fis){

        if(fis != null){

            try{

                fis.close();

            }catch (IOException e){

                e.printStackTrace();

            }

        }

    }

    public static void safeClose(ZipInputStream fis){

        if(fis != null){

            try{

                fis.close();

            }catch (IOException e){

                e.printStackTrace();

            }

        }

    }

 

    /**

     * 压缩文件和文件夹

     *

     * @param srcFileString 要压缩的文件或文件夹

     * @param zipFileString 解压完成的Zip路径

     * @throws Exception

     */

    public static void ZipFolder(String srcFileString, String zipFileString) {

        FileOutputStream fis = null;

        ZipOutputStream outZip = null;

        try{

            fis = new FileOutputStream(zipFileString);

            //创建ZIP

            outZip = new ZipOutputStream(fis);

            //创建文件

            File file = new File(srcFileString);

            //压缩

            ZipFiles(file.getParent() + File.separator, file.getName(), outZip);

            //完成和关闭

            outZip.finish();

            outZip.close();

            fis.close();

        }catch (Exception e){

            e.printStackTrace();

        }finally {

            if(fis != null){

                safeClose(fis);

            }

            if(outZip != null){

                safeClose1(outZip);

            }

        }

    }

 

    public static void safeClose(FileOutputStream fis){

        if(fis != null){

            try {

                fis.close();

            } catch (IOException e) {

                e.printStackTrace();

            }

        }

    }

    public static void safeClose1(ZipOutputStream fis){

        if(fis != null){

            try {

                fis.close();

            } catch (IOException e) {

                e.printStackTrace();

            }

        }

    }

 

    /**

     * 压缩文件

     *

     * @param folderString

     * @param fileString

     * @param zipOutputSteam

     * @throws Exception

     */

    private static void ZipFiles(String folderString, String fileString, ZipOutputStream zipOutputSteam) {

        FileInputStream inputStream = null;

        try{

            if (zipOutputSteam == null)

                return;

            File file = new File(folderString + fileString);

            if (file.isFile()) {

                ZipEntry zipEntry = new ZipEntry(fileString);

                inputStream = new FileInputStream(file);

                zipOutputSteam.putNextEntry(zipEntry);

                int len;

                byte[] buffer = new byte[4096];

                while ((len = inputStream.read(buffer)) != -1) {

                    zipOutputSteam.write(buffer, 0, len);

                }

                zipOutputSteam.closeEntry();

            } else {

                //文件夹

                String fileList[] = file.list();

                //没有子文件和压缩

                if (fileList.length <= 0) {

                    ZipEntry zipEntry = new ZipEntry(fileString + File.separator);

                    zipOutputSteam.putNextEntry(zipEntry);

                    zipOutputSteam.closeEntry();

                }

                //子文件和递归

                for (int i = 0; i < fileList.length; i++) {

                    ZipFiles(folderString + fileString + "/", fileList[i], zipOutputSteam);

                }

            }

        }catch (Exception e){

            e.printStackTrace();

        }finally {

            if(inputStream != null){

                safeClose(inputStream);

            }

        }

    }

 

    public static Bitmap getBitmap(File photoFile) {

        InputStream fis = null;

        try {

            fis = AesUtil.decrypt(photoFile, AesUtil.toKey(MyApplication.getInstance().getAESKey().getBytes()));

            return BitmapFactory.decodeStream(fis);  ///把流转化为Bitmap图片

        } catch (FileNotFoundException e) {

            e.printStackTrace();

            MyLog.e("mylog", "e1:" + e.getMessage());

            return null;

        } catch (Exception e) {

            e.printStackTrace();

            MyLog.e("mylog", "e2:" + e.getMessage());

            return null;

        } finally {

            if(fis != null){

                safeClose(fis);

            }

        }

    }

 

    public static void safeClose(InputStream fis){

        if(fis != null){

            try{

                fis.close();

            }catch (IOException e){

                e.printStackTrace();

            }

        }

    }

 

    public static File getPhotoFile(String nonet, String fileAbsolutePath) {

        File file = new File(fileAbsolutePath);

        File[] subFile = file.listFiles();

        if (subFile != null) {

            for (int i = 0; i < subFile.length; i++) {

                // 判断是否为文件夹

                /*if (subFile[i].isDirectory()) {

                    getPhotoFile(idNonet, subFile[i].getAbsolutePath());

                } else {*/

                String filename = subFile[i].getName();

                if (!TextUtils.isEmpty(filename) && filename.length() >= 13 && nonet != null) {

                    String subFilename = filename.substring(filename.length() - 13, filename.length() - 4);

//                MyLog.e("mylog", "subFilename:" + subFilename + "  nonet:" + nonet);

                    if (subFilename.equals(nonet)) {

                        MyLog.e("mylog", "filename:" + filename);

                        return subFile[i];

                    }

                }

            }

        }

        return null;

    }

 

    /**

     * @param zipName  压缩文件的路径

     * @param filePath 被压缩文件的路径

     * @param password 加密

     * @description:压缩以及加密

     * @author: renbo

     * @date: 2021年5月19日 下午3:35:33

     */

    public static void unZipPass(String zipName, String filePath, String password) throws ZipException {

        ZipFile zipFile = new ZipFile(zipName);

        ArrayList<File> filesToAdd = new ArrayList<File>();

        File root = new File(filePath);

        File[] files = root.listFiles();

        for (File file : files) {

            if (file.isDirectory()) {

                filesToAdd.add(new File(file.getAbsolutePath()));

            } else {

                filesToAdd.add(new File(file.getAbsolutePath()));

            }

        }

        ZipParameters parameters = new ZipParameters();

        parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE); // set

        parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);

        parameters.setEncryptFiles(true);

        parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_AES);

        parameters.setAesKeyStrength(Zip4jConstants.AES_STRENGTH_256);

        // Set password

        parameters.setPassword(password);

        zipFile.addFiles(filesToAdd, parameters);

    }

 

    /**

     * 删除单个文件

     *

     * @param filePath 被删除文件的文件名

     * @return 文件删除成功返回true,否则返回false

     */

    public static boolean deleteFile(String filePath) {

        File file = new File(filePath);

        if (file.isFile() && file.exists()) {

            return file.delete();

        }

        return false;

    }

 

    /**

     * 删除文件夹以及目录下的文件

     *

     * @param filePath 被删除目录的文件路径

     * @return 目录删除成功返回true,否则返回false

     */

    public static boolean deleteDirectory(String filePath) {

        boolean flag = false;

        //如果filePath不以文件分隔符结尾,自动添加文件分隔符

        if (!filePath.endsWith(File.separator)) {

            filePath = filePath + File.separator;

        }

        File dirFile = new File(filePath);

        if (!dirFile.exists() || !dirFile.isDirectory()) {

            return false;

        }

        flag = true;

        File[] files = dirFile.listFiles();

        //遍历删除文件夹下的所有文件(包括子目录)

        for (int i = 0; i < files.length; i++) {

            if (files[i].isFile()) {

                //删除子文件

                flag = deleteFile(files[i].getAbsolutePath());

                if (!flag) break;

            } else {

                //删除子目录

                flag = deleteDirectory(files[i].getAbsolutePath());

                if (!flag) break;

            }

        }

        if (!flag) return false;

        //删除当前空目录

        return dirFile.delete();

    }

 

    /**

     * 根据路径删除指定的目录或文件,无论存在与否

     *

     * @param filePath 要删除的目录或文件

     * @return 删除成功返回 true,否则返回 false。

     */

    public static boolean DeleteFolder(String filePath) {

        File file = new File(filePath);

        if (!file.exists()) {

            return false;

        } else {

            if (file.isFile()) {

                // 为文件时调用删除文件方法

                return deleteFile(filePath);

            } else {

                // 为目录时调用删除目录方法

                return deleteDirectory(filePath);

            }

        }

    }

 

}

本地数据库类-MySQLiteHelper

Android 创建本地数据库

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

/**

 * 数据库帮助类

 */

public class MySQLiteHelper extends SQLiteOpenHelper {

    private static String initSqlFile = Environment.getExternalStorageDirectory().getAbsolutePath();

    private static String REALPATH = initSqlFile+ File.separator+"XXXX"; //需要创建的路径

    private static String REALFILE = REALPATH + File.separator +"xxxx.db"; //需要创建的文件

    private static MySQLiteHelper db;

    private static final int DATEBASE_VERSION = 1;  //定义版本号

    public static String getRealPath(){

        return REALPATH;

    }

    public static String getRealFile(){

        return REALFILE;

    }

    public static void CloseDB(){

        db.close();

    }

 

    //自定义构造方法,简化自动生成的构造方法,path 是主要指定创建db文件的路径

    public MySQLiteHelper(Context context){

        this(context,REALFILE,null,DATEBASE_VERSION);

        MyLog.e("mylog","文件路径:"+REALFILE);

    }

 

    //实现接口必须实现的构造方法

    public MySQLiteHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version){

        super(context, name, factory, version);

    }

 

    @Override

    public void onCreate(SQLiteDatabase sqLiteDatabase) {

        //第一次创建数据库时,才会调用

        MyLog.e("mylog","创建数据库");

        sqLiteDatabase.execSQL(TableA.CREAT_TABLE(TableA.TABLE_NAME())); //创建表

        sqLiteDatabase.execSQL(TableB.CREAT_TABLE(TableB.TABLE_NAME())); //创建表

    }

 

    @Override

    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {

    }

}

TableA对于的类

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

/**

 * 对应数据表的类

 */

public class TableA {

    public static  String TABLE_NAME(){

        return "table_a";

    }

    public static final String id = "id"; //ID

    public static final String s1= "s1";//字段s1

    public static final String s1= "s2";//字段s2

    public static final String s1= "s3";//字段s3

    public static final String s1= "s4";//字段s4

    public static final String s1= "s5";//字段s5

    public static final String s1= "s6";//字段s6

 

    public static String CREAT_TABLE(String tableName){

        return new StringBuffer().

                append("CREATE TABLE IF NOT EXISTS ").append(tableName).

                append("(").

                append(id).append(" INTEGER PRIMARY KEY AUTOINCREMENT,").

                append(s1).append(" TEXT,").

                append(s2).append(" TEXT,").

                append(s3).append(" TEXT,").

                append(s4).append(" TEXT,").

                append(s5).append(" TEXT,").

                append(s6).append(" TEXT").

                append(");").toString();

    }

}

访问webservice封装-HttpUtils

对访问webservice 接口的请求封装

引入的包

1

implementation files('libs\\ksoap2-android-assembly-3.3.0-jar-with-dependencies.jar')

代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

import org.ksoap2.serialization.SoapObject;

import org.ksoap2.serialization.SoapSerializationEnvelope;

import org.ksoap2.transport.HttpTransportSE;

import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;

import java.util.Base64;

 

public class HttpUtils {

    private static final String serviceNameSapce = "http://webservice.cps.xxx.com/";

    private static MyApplication myApplication = MyApplication.getInstance();

    private HttpUtils() {

    }

 

    //    登录

    public static String login(String METHODNAME, String username, String password,String pingid) {

        SoapObject request = new SoapObject(serviceNameSapce, METHODNAME);

        request.addProperty("username", jiami(username));

        request.addProperty("password", jiami(password));

        request.addProperty("pingid",jiami(pingid));

        request.addProperty("pingidly",null);

        return scop(request);

    }

  

    private static String scop(SoapObject request) {

        //创建SoapSerializationEnvelope 对象,同时指定soap版本号

        SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapSerializationEnvelope.VER10);

        envelope.bodyOut = request;//由于是发送请求,所以是设置bodyOut

        envelope.dotNet = false;//由于是.net开发的webservice

        envelope.setOutputSoapObject(request);

 

        HttpTransportSE httpTransportSE = new HttpTransportSE(getURl(), 400000);

        try {

            httpTransportSE.call(null, envelope);//调用

        } catch (IOException e) {

            e.printStackTrace();

            return "{\"error\":\"" + e.getMessage() + "\"}";

        } catch (XmlPullParserException e) {

            e.printStackTrace();

            return "{\"error\":\"" + e.getMessage() + "\"}";

        }

 

        // 获取返回的数据

        SoapObject object = (SoapObject) envelope.bodyIn;

        return object.getProperty(0).toString();

    }

 

    public static String jiami(String str) { //加密

        return AesUtil.aesEncrypt(str, MyApplication.getInstance().getAESKey());

    }

    public static String jiemi(String str){ //解密

        return AesUtil.aesDecrypt(str,MyApplication.getInstance().getAESKey());

    }

    public static String getURl(){

        return myApplication.getIP()+myApplication.getIP_SUFFIX();

    }

}

Toolbar封装类-MaterialToolbar

布局文件

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

<com.google.android.material.appbar.MaterialToolbar

        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"

        android:id="@+id/titlebar"

        android:background="@color/primary1"

        style="@style/Widget.MaterialComponents.Toolbar.Surface"

        app:layout_constraintTop_toTopOf="parent"

        app:layout_constraintLeft_toLeftOf="parent"

        app:layout_constraintRight_toRightOf="parent"

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        app:navigationIcon="@mipmap/back"

        app:title="XXXX"

        app:titleTextColor="@color/white"

        app:titleCentered="true"

        app:titleTextAppearance="@style/Text18wb"

        app:subtitle="xxxx年xx月xx日 星期x"

        app:subtitleTextColor="@color/white"

        app:subtitleCentered="true"

        app:subtitleTextAppearance="@style/Text12w"

        app:menu="@menu/scan_menu"/>

配置文件

1、input_menu.xml

1

2

3

4

5

6

7

8

9

10

<?xml version="1.0" encoding="utf-8"?>

<menu xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:app="http://schemas.android.com/apk/res-auto">

 

    <!--showAsAction的值always一直显示,ifRoom如果有地方就显示,没有则隐藏,never一直隐藏-->

    <item android:id="@+id/owner"

        android:title="个人中心"

        android:icon="@mipmap/owner1"

        app:showAsAction="always"/>

</menu>

2、scan_menu.xml

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

<?xml version="1.0" encoding="utf-8"?>

<menu xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:app="http://schemas.android.com/apk/res-auto">

 

    <!--showAsAction的值always一直显示,ifRoom如果有地方就显示,没有则隐藏,never一直隐藏-->

    <item android:id="@+id/clean"

        android:title="一键清空"

        android:icon="@mipmap/clean1"

        app:showAsAction="ifRoom"/>

    <item

        android:id="@+id/input"

        android:title="行李补录"

        android:icon="@mipmap/shoudong"

        app:showAsAction="ifRoom"/>

 

<!--    <item-->

<!--        android:id="@+id/setting"-->

<!--        android:title="Setting"-->

<!--        android:icon="@mipmap/ic_launcher"-->

<!--        app:showAsAction="never"/>-->

</menu>

初始化

1

2

3

4

5

private void initToolBar(){

        flightInputBinding.titlebar.setTitle("航班设置");

        flightInputBinding.titlebar.setSubtitle(myApplication.getDATE_WEEK());

        setSupportActionBar(flightInputBinding.titlebar);

    }

布局与按钮事件

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

@Override

public boolean onCreateOptionsMenu(Menu menu) {

    getMenuInflater().inflate(R.menu.input_menu, menu);

    return super.onCreateOptionsMenu(menu);

}

@Override

public boolean onOptionsItemSelected(@NonNull MenuItem item) {

    int id = item.getItemId();

    if(id == android.R.id.home){

        Dialog.showFinishDialog(this, "确定要退出APP么?",

                () -> myApplication.finishAllActivity());

    }else if(id == R.id.owner){

        Intent i = new Intent(FlightInputActivity.this,InfomationActivity.class);

        startActivityForResult(i,2001);

    }

    return super.onOptionsItemSelected(item);

}

网络请求框架-OkGo

引入包

1

implementation 'com.lzy.net:okgo:3.0.4'

工具类

1、TrustAllCerts

此类用于绕过https验证

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

package com.kaiya.mvp.npm_ar.utils;

import java.security.SecureRandom;

import java.security.cert.CertificateException;

import java.security.cert.X509Certificate;

 

import javax.net.ssl.HostnameVerifier;

import javax.net.ssl.SSLContext;

import javax.net.ssl.SSLSession;

import javax.net.ssl.SSLSocketFactory;

import javax.net.ssl.TrustManager;

import javax.net.ssl.X509TrustManager;

 

/**

 * Created by gang.qin

 * Date:2024/3/19 15:05

 * 质量、速度、廉价,选择其中两个 --- 匿名

 */

 

//public class TrustAllCerts implements X509TrustManager {

//    @Override

//    public void checkClientTrusted(X509Certificate[] chain, String authType) {}

//

//    @Override

//    public void checkServerTrusted(X509Certificate[] chain, String authType) {}

//

//    @Override

//    public X509Certificate[] getAcceptedIssuers() {return new X509Certificate[0];}

//}

 

public class TrustAllCerts implements X509TrustManager {

    @Override

    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {

    }

 

    @Override

    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {

 

        if (chain == null) {

            throw new IllegalArgumentException("  Check Server x509Certificates is null");

        }

    }

 

    @Override

    public X509Certificate[] getAcceptedIssuers() {

        return new X509Certificate[0];

    }

 

 

    public static SSLSocketFactory createSSLSocketFactory() {

        SSLSocketFactory ssfFactory = null;

 

        try {

            SSLContext sc = SSLContext.getInstance("TLS");

            sc.init(null, new TrustManager[]{new TrustAllCerts()}, new SecureRandom());

 

            ssfFactory = sc.getSocketFactory();

        } catch (Exception e) {

        }

 

        return ssfFactory;

    }

 

    public static class TrustAllHostnameVerifier implements HostnameVerifier {

        @Override

        public boolean verify(String hostname, SSLSession session) {

            return true;

        }

    }

 

 

}

2、封装

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

package com.kaiya.mvp.npm_ar.utils;

 

import android.app.Application;

import android.content.Context;

import android.transition.TransitionManager;

 

import com.lzy.okgo.OkGo;

import com.lzy.okgo.cookie.CookieJarImpl;

import com.lzy.okgo.cookie.store.MemoryCookieStore;

import com.lzy.okgo.interceptor.HttpLoggingInterceptor;

 

import java.security.KeyManagementException;

import java.security.NoSuchAlgorithmException;

import java.security.SecureRandom;

import java.security.cert.CertificateException;

import java.security.cert.X509Certificate;

import java.util.concurrent.TimeUnit;

import java.util.logging.Level;

 

import javax.net.ssl.HostnameVerifier;

import javax.net.ssl.SSLContext;

import javax.net.ssl.SSLSession;

import javax.net.ssl.TrustManager;

import javax.net.ssl.X509TrustManager;

 

import okhttp3.OkHttpClient;

 

/**

 * Created by gang.qin

 * Date:2024/3/20 15:41

 * 质量、速度、廉价,选择其中两个 --- 匿名

 */

public class OkGoUtils {

    public static X509TrustManager xtm;

    public static SSLContext sslContext;

    public static void initOkGo(Application application){

        xtm = new X509TrustManager() {

            @Override

            public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

 

            }

 

            @Override

            public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

 

            }

 

            @Override

            public X509Certificate[] getAcceptedIssuers() {

                return new X509Certificate[0];

            }

        };

        try {

            sslContext = SSLContext.getInstance("SSL");

 

            sslContext.init(null, new TrustManager[]{xtm}, new SecureRandom());

 

        } catch (NoSuchAlgorithmException e) {

            e.printStackTrace();

        } catch (KeyManagementException e) {

            e.printStackTrace();

        }

        HostnameVerifier DO_NOT_VERIFY = (hostname, session) -> true;

        //        OkGo.getInstance().init(this); //最简单的配置 什么都不需要写 全部使用默认参数

        OkHttpClient.Builder builder = new OkHttpClient.Builder();

//可以使用OkGo内置的log拦截器打印log,如果你觉得不好用,也可以自己写个,这个没有限制。

        HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor("OkGo");

//log打印级别

        loggingInterceptor.setPrintLevel(HttpLoggingInterceptor.Level.BODY);

//log颜色级别

        loggingInterceptor.setColorLevel(Level.ALL);

        builder.addInterceptor(loggingInterceptor);

        //全局的读取超时时间

        builder.readTimeout(OkGo.DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS);

//全局的写入超时时间

        builder.writeTimeout(OkGo.DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS);

//全局的连接超时时间

        builder.connectTimeout(OkGo.DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS);

        /*

     *  connectTimeout:指客户端和服务器 建立通道 的时间

        writeTimeout:客户端把数据写出去需要的时间

        readTimeout:客户端等待服务器返回数据的时间

        * */

        //使用内存保持cookie,app退出后,cookie消失

        builder.cookieJar(new CookieJarImpl(new MemoryCookieStore()));

        if(sslContext != null){

            builder.sslSocketFactory(sslContext.getSocketFactory(),xtm)

                    .hostnameVerifier(DO_NOT_VERIFY)

                    .build();

        }else{

            MyLog.e("mylog","过滤器出错!");

        }

        OkGo.getInstance().init(application)//必须调用初始化

                .setOkHttpClient(builder.build())  //建议设置OkHttpClient,不设置将使用默认的

                .setRetryCount(1); //超时重连,本身1次,我这边设置1次,总共2次访问

    }

 

    public static OkHttpClient initOkhttp(){

        OkHttpClient client = new OkHttpClient.Builder()

                .sslSocketFactory(TrustAllCerts.createSSLSocketFactory())

                .hostnameVerifier(new TrustAllCerts.TrustAllHostnameVerifier())

                .build();

        return client;

    }

}

POST请求

1

2

3

4

5

6

7

8

9

10

    private static void okgoPost(String method, HashMap<String,String> hashMap, OkGoCallback callback){

    OkGo.<String>post(getIP()+method)

            .params(hashMap)

            .execute(new StringCallback() {

                @Override

                public void onSuccess(Response<String> response) {

                    callback.callback(response.body());

                }

            });

}

下载

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

OkGo.<File>get(uploadUrl)

           .tag(this)

           //.headers("header1", "headerValue1")//

           //.params("param1", "paramValue1")//

           .execute(new FileCallback(

                   saveFilePath,

                   saveName

           ) {

               @Override

               public void onStart(com.lzy.okgo.request.base.Request<File, ? extends com.lzy.okgo.request.base.Request> request) {

                   super.onStart(request);

                   MyLog.e("mylog","开始下载");

               }

 

               @Override

               public void onSuccess(com.lzy.okgo.model.Response<File> response) {

                   progress.getProgress(100,"success");

               }

 

               @Override

               public void onError(com.lzy.okgo.model.Response<File> response) {

                   super.onError(response);

                   progress.getProgress(-1,"下载出错!");

 

               }

 

               @Override

               public void downloadProgress(com.lzy.okgo.model.Progress pp) {

                   super.downloadProgress(pp);

                   int ppi = (int)(pp.fraction * 100);

                   MyLog.e("mylog","progress:"+ppi);

                   progress.getProgress(ppi,"");

               }

           });

网络请求框架-OkHttp

引入包

1

implementation 'com.squareup.okhttp3:okhttp:4.10.0'

封装

TrustAllCerts类 在OkGo中 。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

private static String okhttp(String method , String json){

       MyLog.e("mylog-url",getIP()+method);

               OkHttpClient client = new OkHttpClient.Builder()

               .sslSocketFactory(TrustAllCerts.createSSLSocketFactory()) //绕过https

               .hostnameVerifier(new TrustAllCerts.TrustAllHostnameVerifier()) //绕过https

               .build();

       RequestBody body = RequestBody.create(json, JSON);

       Request request = new Request.Builder()

               .url( getIP()+method )

               .post(body)

               .build();

       try{

           Response response = client.newCall(request).execute();

           return Objects.requireNonNull(response.body()).string();

       }catch (Exception e){

           MyLog.e("mylog","error:\r\n"+e.getMessage());

           return "error:\r\n"+e.getMessage();

       }

   }

调用

1

2

3

GetList list = new GetList(flightDate,flightNo,sourceAirport, myApplication.getAppIp()); //参数类

//list.toString() 为 类转json字符串

String response = okhttp(GET_LIST,list.toString());

下载

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

/**

     *

     * @param uploadUrl 下载路径

     * @param saveFilePath 保存路径

     * @param saveName 保存文件名 ,如 XXX.apk

     * @param progress 回调函数,获取下载进度

     */

    public void downloadApk(String uploadUrl,String saveFilePath,String saveName,Progress progress) {

        // 创建OkHttpClient并配置自定义的TrustManager

        OkHttpClient client = new OkHttpClient.Builder()

                .sslSocketFactory(TrustAllCerts.createSSLSocketFactory())

                .hostnameVerifier(new TrustAllCerts.TrustAllHostnameVerifier())

                .build();

        Request request = new Request.Builder()

                .url(uploadUrl)

                .build();

        Call call = client.newCall(request);

        call.enqueue(new Callback() {

            @Override

            public void onFailure(@NotNull Call call, @NotNull IOException e) {

                progress.getProgress(-1,e.getMessage());

            }

 

            @Override

            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {

                //3824043

                long fileMax = response.body().contentLength();

                InputStream inputStream = Objects.requireNonNull(response.body()).byteStream();

                File target = new File(saveFilePath,saveName);

                FileOutputStream fileOutputStream = new FileOutputStream(target);

 

                try {

                    byte[] buffer = new byte[2048];

                    int len;

                    while ((len = inputStream.read(buffer)) != -1) {

                        fileOutputStream.write(buffer, 0, len);

                        int p =  (int) ((target.length() * 100) / fileMax);

                        progress.getProgress(p,"");

                    }

                    fileOutputStream.flush();

                } catch (IOException e) {

                    e.printStackTrace();

                }

            }

        });

 

    }


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 :
相关文章
  • Android Service功能使用介绍
    在Android开发中,Service是一个在后台长时间运行的组件,不会提供用户界面。它可以用来处理一些需要在后台进行的操作,比如播放音乐、下
  • Android封装常用工具类的介绍
    日志封装类-MyLog 是对androidlog的封装,封装后 可以设置显示级别 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
  • Flutter web bridge通信总结分析介绍

    Flutter web bridge通信总结分析介绍
    公司医疗业务人手比较少【小而美】的团队~ 较少采用的前端技术架构是: toC:小程序 toB2C: Flutter + H5(SPA - React)【build ???????? Android + IOS】
  • Android Flutter自定义动画路由的介绍

    Android Flutter自定义动画路由的介绍
    flutter中有默认的Route组件,叫做MaterialPageRoute,一般情况下我们在flutter中进行跳转的话,只需要向Navigator中传入一个MaterialPageRoute就可以了。
  • Android实现获取短信验证码并自动填充

    Android实现获取短信验证码并自动填充
    最近弄了个短信自动填充功能,一开始觉得很简单,不就是动态注册个广播接收器去监听短信消息不就可以了吗?结果没这么简单,问题就
  • Android studio六大基本布局介绍
    Android中常用的布局方式有以下几种: 线性布局LinearLayout 相对布局RelativeLayout 表格布局TableLayout 层布局FrameLayout 绝对布局AbsoluteLayout 网格布
  • Android Service启动绑定流程介绍
    本文基于Android 11,参考《Android进阶解密》一书资料。了解Service的启动和绑定流程,以及Service的Context创建过程。 由于基于分析流程,忽略
  • Android自定义有限制区域的图例角度自识别涂鸦工

    Android自定义有限制区域的图例角度自识别涂鸦工
    上文Android:实现一个自定义有限制区域的图例(角度自识别)涂鸦工具类(中)中我们已经实现了在复杂的异形区域中涂鸦,最后生成图片
  • Android自定义有限制区域图例角度自识别涂鸦工具

    Android自定义有限制区域图例角度自识别涂鸦工具
    上文Android:实现一个自定义有限制区域的图例(角度自识别)涂鸦工具类(上)中我们已经实现了自定义View签名的功能,包含撤回、清除方
  • Flutter配置代理抓包实现过程介绍

    Flutter配置代理抓包实现过程介绍
    在开发Flutter中,我们经常需要对网络请求进行调试,而Flutter自带的devtool的network又不太好用,有时会出现请求成功,但是又看不到response返
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计