1.Code in Activity
package com.me.mydemos.ui.activity.excel; import android.Manifest; import android.annotation.SuppressLint; import android.app.Activity; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Build; import android.os.Environment; import android.util.Log; import android.widget.Toast; import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; import androidx.core.app.ActivityCompat; import com.me.mydemos.base.BaseActivity; import com.me.mydemos.databinding.ActivityExcelImportExportBinding; import com.me.mydemos.ui.excel.SheetHelper; import com.me.mydemos.util.FileUtils2; import com.me.mydemos.util.LogUtil; import com.tbruyelle.rxpermissions2.RxPermissions; import java.util.ArrayList; import java.util.List; public class ExcelImportExportActivity extends BaseActivity<ActivityExcelImportExportBinding> { public static final String DOC = "application/msword"; public static final String DOCX = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"; public static final String XLS = "application/vnd.ms-excel application/x-excel"; public static final String XLSX = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; public static final String PPT = "application/vnd.ms-powerpoint"; public static final String PPTX = "application/vnd.openxmlformats-officedocument.presentationml.presentation"; public static final String PDF = "application/pdf"; @Override protected int getLayoutId() { return 0; } @Override protected void init() { //Export binding.tvExport.setOnClickListener(v -> { initPermission(); }); //Import binding.tvImport.setOnClickListener(v -> { Intent intent = new Intent(Intent.ACTION_GET_CONTENT); // intent.setType("*/*");//Set the type, here it is any type, any suffix can be written like this. intent.setType(XLS + "|" + XLSX); intent.addCategory(Intent.CATEGORY_OPENABLE); startActivityForResult(intent, 1000); }); } private boolean havePermission = false; private static final int REQUEST_EXTERNAL_STORAGE = 1; private static String[] PERMISSIONS_STORAGE = { Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE }; private AlertDialog dialog; private void checkPermission() { // Check whether the permission (NEED_PERMISSION) is authorized. PackageManager.PERMISSION_GRANTED indicates consent to authorization. if (Build.VERSION.SDK_INT >= 30) { if (!Environment.isExternalStorageManager()) { if (dialog != null) { dialog.dismiss(); dialog = null; } dialog = new AlertDialog.Builder(this) .setTitle("Prompt")//Set title .setMessage("Please enable file access permission, otherwise this application cannot be used normally!") .setNegativeButton("Cancel", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int i) { dialog.dismiss(); } }) .setPositiveButton("OK", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); // Intent intent = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION); // startActivity(intent); } }).create(); dialog.show(); } else { havePermission = true; Log.i("swyLog", "Android 11 or above, currently has permission"); initPermission(); } } else { if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) { if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { //request for access if (dialog != null) { dialog.dismiss(); dialog = null; } dialog = new AlertDialog.Builder(this) .setTitle("Prompt")//Set title .setMessage("Please enable file access permission, otherwise this application cannot be used normally!") .setPositiveButton("OK", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); ActivityCompat.requestPermissions(ExcelImportExportActivity.this, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE); } }).create(); dialog.show(); } else { havePermission = true; Log.i("swyLog", "Android 6.0 or above, below 11, currently has permission"); } } else { havePermission = true; Log.i("swyLog", "Android 6.0 or below, permission has been obtained"); } } } private String[] getReadWritePermissions() { // LogUtil.d("Build.VERSION.SDK_INT:" + Build.VERSION.SDK_INT); // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { // return new String[]{ // android.Manifest.permission.WRITE_EXTERNAL_STORAGE, // android.Manifest.permission.READ_MEDIA_IMAGES, // android.Manifest.permission.READ_MEDIA_AUDIO, // android.Manifest.permission.READ_MEDIA_VIDEO // }; // } else { return new String[]{ android.Manifest.permission.WRITE_EXTERNAL_STORAGE, android.Manifest.permission.READ_EXTERNAL_STORAGE }; // } } @SuppressLint("CheckResult") private void initPermission() { RxPermissions permissions = new RxPermissions(this); permissions.request( android.Manifest.permission.WRITE_EXTERNAL_STORAGE, android.Manifest.permission.READ_EXTERNAL_STORAGE ).subscribe(result -> { if (result) { new Thread(new Runnable() { @Override public void run() { List<SheetHelper.DeviceInfo> deviceInfos = new ArrayList<>(); for (int i = 0; i < 20; i + + ) { SheetHelper.DeviceInfo deviceInfo = new SheetHelper.DeviceInfo(); deviceInfo.setRow(String.valueOf(i + 1));//serial number deviceInfo.setDeviceId("1531359236" + i);//device id deviceInfo.setPhoneBrand("Huawei" + i);//Mobile phone brand deviceInfo.setLatestLocation("Beijing" + i);//Latest location deviceInfo.setChangeSum(String.valueOf(i));//Number of times to change devices and cards deviceInfo.setInstallAppSum(String.valueOf(i));//Number of application installations deviceInfo.setUninstallAppSum(String.valueOf(i));//Number of uninstalled applications deviceInfo.setViolationAppSum(String.valueOf(i));//Number of violating apps deviceInfos.add(deviceInfo); } String[] title = {"Serial number", "Device number", "Mobile phone brand", "Latest location", "Number of phone and card changes", "Number of application installations", "Number of uninstalled applications", "Number of illegal apps" "}; boolean isSuccess = SheetHelper.exportExcel(title, deviceInfos, "exportExcel", "Export Test", ExcelImportExportActivity.this, true); runOnUiThread(() -> { if (isSuccess) { Toast.makeText(ExcelImportExportActivity.this, "Export successful", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(ExcelImportExportActivity.this, "Export failed", Toast.LENGTH_SHORT).show(); } }); } }).start(); } else { Toast.makeText(context, "Please grant the application read and write permissions", Toast.LENGTH_SHORT).show(); } }); } @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); try { if (resultCode == Activity.RESULT_OK & amp; & amp; requestCode == 1000) { Uri uri = data.getData();//Get the uri, and then the process of converting the uri into file. LogUtil.d("uri:" + uri.getPath()); String absolutePath = FileUtils2.getUriPath(this, uri); Log.d("File selected", "File path:" + absolutePath); new Thread(new Runnable() { @Override public void run() { List<String> strings = SheetHelper.readExcel(absolutePath); runOnUiThread(new Runnable() { @Override public void run() { if (strings != null) { String str = ""; for (String string : strings) { String[] split = string.split(" & amp; & amp;"); for (String s : split) { Log.i("Get data", s); str + = s; } str + = "\ "; } LogUtil.d("data: " + str); Toast.makeText(context, "Import successful", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(context, "Import failed", Toast.LENGTH_SHORT).show(); } } }); } }).start(); } } catch (Exception e) { Toast.makeText(context, "Import exception", Toast.LENGTH_SHORT).show(); e.printStackTrace(); } } @Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch (requestCode) { case REQUEST_EXTERNAL_STORAGE: { if (grantResults.length > 0 & amp; & amp; grantResults[0] == PackageManager.PERMISSION_GRANTED) { havePermission = true; Toast.makeText(this, "Authorization successful!", Toast.LENGTH_SHORT).show(); initPermission(); } else { havePermission = false; Toast.makeText(this, "Authorization denied!", Toast.LENGTH_SHORT).show(); } } } } }
2.AndroidManifest.xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" /> <!--Android 13 READ_MEDIA_IMAGE, READ_MEDIA_VIDEO, READ_MEDIA_AUDIO replace READ_EXTERNAL_STORAGE--> <!-- Generally speaking, apps that allow users to customize avatars require this permission --> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" android:minSdkVersion="33" /> <!-- If you want to develop an app that needs to obtain audio, such as a music player, add this permission --> <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" android:minSdkVersion="33" /> <!-- If you want to develop an app that needs to obtain videos, such as a video editor, add this permission --> <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" android:minSdkVersion="33" /> <!-- Forward compatible --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" /> <!--Android 11 file read and write permissions--> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" /> <!--Allow mounting and unloading file system permissions--> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" tools:ignore="ProtectedPermissions" /> <!--Import and export--> <provider android:name="androidx.core.content.FileProvider" android:authorities="com.me.mydemos.fileProvider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider>
3. res/xml/file_paths.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <paths> <root-path name="root" path="" /> <files-path name="files" path="" /> <cache-path name="cache" path="" /> <external-path name="external" path="" /> <external-files-path name="external_file_path" path="" /> <external-cache-path name="external_cache_path" path="" /> </paths> </resources>