├── .gitignore ├── .idea ├── gradle.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── zqw │ │ └── fileoperation │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── zqw │ │ │ └── fileoperation │ │ │ ├── MainActivity.java │ │ │ ├── MyApplication.java │ │ │ ├── RequestPermissionActivity.java │ │ │ ├── adapters │ │ │ ├── MyAdapter.java │ │ │ ├── OnFileItemClickListener.java │ │ │ ├── OnItemClickListener.java │ │ │ └── PreviewBarAdapter.java │ │ │ ├── fragments │ │ │ └── FolderFragment.java │ │ │ ├── functions │ │ │ ├── FileFounder.java │ │ │ ├── MyCompress.java │ │ │ └── RandomNameGenerater.java │ │ │ ├── pojos │ │ │ └── MyFile.java │ │ │ └── tasks │ │ │ ├── CompressTask.java │ │ │ ├── DecompressTask.java │ │ │ └── FilePathTask.java │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ ├── bottom_menu_border.xml │ │ ├── download_list_parentitem.xml │ │ ├── file1.png │ │ ├── folder1.png │ │ ├── folder2.png │ │ ├── ic_launcher_background.xml │ │ ├── myborder.xml │ │ ├── selected_ripple.xml │ │ └── test1.xml │ │ ├── layout │ │ ├── activity_filelist.xml │ │ ├── activity_main.xml │ │ ├── activity_request_permission.xml │ │ ├── bottom_popup_menu.xml │ │ ├── file_item.xml │ │ ├── folder_fragment.xml │ │ ├── item_listview.xml │ │ ├── layouttest.xml │ │ └── preview_bar_item_layout.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── zqw │ └── fileoperation │ ├── ExampleUnitTest.java │ ├── FileTest.java │ └── Main.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16 | 26 | 27 | 28 | 29 | 30 | 31 | 33 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # androidfilemanager 2 | 安卓文件管理器 3 | 有问题联系qq 513768474 4 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 26 5 | defaultConfig { 6 | applicationId "com.zqw.fileoperation" 7 | minSdkVersion 21 8 | targetSdkVersion 26 9 | versionCode 1 10 | versionName "1.0" 11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | implementation fileTree(dir: 'libs', include: ['*.jar']) 23 | implementation 'com.android.support:appcompat-v7:26.1.0' 24 | implementation 'com.android.support:recyclerview-v7:26.1.0' 25 | implementation 'com.android.support.constraint:constraint-layout:1.0.2' 26 | testImplementation 'junit:junit:4.12' 27 | androidTestImplementation 'com.android.support.test:runner:1.0.1' 28 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' 29 | } 30 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/zqw/fileoperation/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.zqw.fileoperation; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.zqw.fileoperation", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/java/com/zqw/fileoperation/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.zqw.fileoperation; 2 | 3 | import android.animation.ValueAnimator; 4 | import android.app.AlertDialog; 5 | import android.app.FragmentManager; 6 | import android.app.FragmentTransaction; 7 | import android.content.DialogInterface; 8 | import android.os.Bundle; 9 | import android.support.v4.widget.SwipeRefreshLayout; 10 | import android.support.v7.app.AppCompatActivity; 11 | import android.support.v7.widget.LinearLayoutManager; 12 | import android.support.v7.widget.RecyclerView; 13 | import android.text.Editable; 14 | import android.util.Log; 15 | import android.util.TypedValue; 16 | import android.view.View; 17 | import android.view.ViewGroup; 18 | import android.widget.Button; 19 | import android.widget.EditText; 20 | import android.widget.LinearLayout; 21 | import android.widget.Toast; 22 | 23 | import com.zqw.fileoperation.adapters.OnItemClickListener; 24 | import com.zqw.fileoperation.adapters.PreviewBarAdapter; 25 | import com.zqw.fileoperation.fragments.FolderFragment; 26 | import com.zqw.fileoperation.functions.MyCompress; 27 | import com.zqw.fileoperation.pojos.MyFile; 28 | import com.zqw.fileoperation.tasks.CompressTask; 29 | import com.zqw.fileoperation.tasks.DecompressTask; 30 | 31 | import java.io.File; 32 | import java.util.ArrayList; 33 | import java.util.LinkedList; 34 | import java.util.List; 35 | 36 | public class MainActivity extends AppCompatActivity implements View.OnClickListener, 37 | FragmentManager.OnBackStackChangedListener, 38 | OnItemClickListener, 39 | SwipeRefreshLayout.OnRefreshListener { 40 | private Button button = null; 41 | private SwipeRefreshLayout swipeRefreshLayout = null; 42 | private int lastBackStackCount = 0; 43 | private Button bottomMenuCompress = null; 44 | private Button bottomMenuDecompress = null; 45 | private int COMPRESS_STATUS_UNDO = 0; 46 | private int COMPRESS_STATUS_SELECTFILES = 1; 47 | private int COMPRESS_STATUS_SELECTZIPFILE = 2; 48 | 49 | 50 | private int compressStatus = COMPRESS_STATUS_UNDO; 51 | 52 | final public FragmentManager manager = getFragmentManager(); 53 | public String currentAbsolutePath = "/storage/emulated/0"; 54 | public List previewBarItems = null; 55 | public PreviewBarAdapter adapter = null; 56 | public RecyclerView previewBar = null; 57 | public LinearLayout bottomPopupMenuLayout = null; 58 | public View fileItemView = null; 59 | //复选框选中的文件 60 | public List selectedUncompressedFiles = new LinkedList<>(); 61 | public List selectedUndecompressedFiles = new LinkedList<>(); 62 | 63 | @Override 64 | protected void onCreate(Bundle savedInstanceState) { 65 | super.onCreate(savedInstanceState); 66 | setContentView(R.layout.activity_main); 67 | //通过id加载控件 68 | previewBar = (RecyclerView) findViewById(R.id.preview_bar); 69 | swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.main_swipe_refresh_layout); 70 | bottomPopupMenuLayout = (LinearLayout) findViewById(R.id.bottom_popup_menu_layout); 71 | bottomMenuCompress = (Button) findViewById(R.id.bottom_popup_menu_compress); 72 | bottomMenuDecompress = (Button) findViewById(R.id.bottom_popup_menu_decompress); 73 | bottomMenuCompress.setOnClickListener(this); 74 | bottomMenuDecompress.setOnClickListener(this); 75 | // linearLayout = (LinearLayout)findViewById(R.id.bottom_popup_menu_layout); 76 | //通过id加载控件 77 | //是否插入内存卡 78 | // Log.d("test", String.valueOf(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))); 79 | FolderFragment folderFragment = new FolderFragment(); 80 | FragmentTransaction transaction = manager.beginTransaction(); 81 | manager.addOnBackStackChangedListener(this); 82 | transaction.add(R.id.folder_fragment_layout, folderFragment); 83 | transaction.commit(); 84 | swipeRefreshLayout.setOnRefreshListener(this); 85 | LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this); 86 | linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); 87 | previewBar.setLayoutManager(linearLayoutManager); 88 | previewBarItems = new ArrayList() {{ 89 | add("/storage/emulated/0"); 90 | }}; 91 | 92 | adapter = new PreviewBarAdapter(previewBarItems); 93 | adapter.setOnItemClickListener(this); 94 | previewBar.setAdapter(adapter); 95 | } 96 | 97 | @Override 98 | public void onRefresh() { 99 | reFresh(true); 100 | swipeRefreshLayout.setRefreshing(false); 101 | } 102 | 103 | @Override 104 | public void onBackStackChanged() { 105 | int backStackEntryCount = manager.getBackStackEntryCount(); 106 | if (backStackEntryCount < lastBackStackCount) { 107 | previewBarItems.remove(previewBarItems.size() - 1); 108 | adapter.notifyItemRemoved(previewBarItems.size()); 109 | } else { 110 | previewBarItems.add(currentAbsolutePath); 111 | adapter.notifyItemInserted(previewBarItems.size() - 1); 112 | } 113 | lastBackStackCount = backStackEntryCount; 114 | } 115 | 116 | @Override 117 | public void onItemClick(View view, int position) { 118 | int times = previewBarItems.size() - 1 - position; 119 | for (int i = 0; i < times; i++) 120 | manager.popBackStack(); 121 | } 122 | 123 | public void reFresh(boolean isHint) { 124 | holdBottomPopMenu(); 125 | FolderFragment folderFragment = (FolderFragment) manager.findFragmentById(R.id.folder_fragment_layout); 126 | folderFragment.onRefresh(); 127 | if (isHint) 128 | Toast.makeText(this, "刷新成功!", Toast.LENGTH_SHORT).show(); 129 | } 130 | 131 | public void onItemLongClick(int position) { 132 | toggleBottomPopupMenu(); 133 | } 134 | 135 | private void holdBottomPopMenu() { 136 | if (bottomPopupMenuLayout.getHeight() == 0) return; 137 | compressStatus = COMPRESS_STATUS_UNDO; 138 | changeTextByStatus(compressStatus); 139 | FolderFragment folderFragment = ((FolderFragment) manager.findFragmentById(R.id.folder_fragment_layout)); 140 | folderFragment.adapter.setChecked(false); 141 | folderFragment.adapter.notifyDataSetChanged(); 142 | final ViewGroup.LayoutParams layoutParams = bottomPopupMenuLayout.getLayoutParams(); 143 | final ValueAnimator animator = ValueAnimator.ofInt(120, 0); 144 | animator.setDuration(600); 145 | animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 146 | @Override 147 | public void onAnimationUpdate(ValueAnimator animation) { 148 | int expectedheight = (int) animation.getAnimatedValue(); 149 | layoutParams.height = ((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, expectedheight, getResources().getDisplayMetrics())); 150 | bottomPopupMenuLayout.setLayoutParams(layoutParams); 151 | } 152 | }); 153 | animator.start(); 154 | selectedUndecompressedFiles.clear(); 155 | selectedUncompressedFiles.clear(); 156 | } 157 | 158 | private void unholdBottomPopupMenu() { 159 | if (bottomPopupMenuLayout.getHeight() == 120) return; 160 | compressStatus = COMPRESS_STATUS_UNDO; 161 | changeTextByStatus(compressStatus); 162 | FolderFragment folderFragment = ((FolderFragment) manager.findFragmentById(R.id.folder_fragment_layout)); 163 | folderFragment.adapter.setChecked(true); 164 | folderFragment.adapter.notifyDataSetChanged(); 165 | final ViewGroup.LayoutParams layoutParams = bottomPopupMenuLayout.getLayoutParams(); 166 | final ValueAnimator animator = ValueAnimator.ofInt(0, 120); 167 | animator.setDuration(600); 168 | animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 169 | @Override 170 | public void onAnimationUpdate(ValueAnimator animation) { 171 | int expectedheight = (int) animation.getAnimatedValue(); 172 | layoutParams.height = ((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, expectedheight, getResources().getDisplayMetrics())); 173 | bottomPopupMenuLayout.setLayoutParams(layoutParams); 174 | } 175 | }); 176 | animator.start(); 177 | } 178 | 179 | private void toggleBottomPopupMenu() { 180 | if (bottomPopupMenuLayout.getHeight() == 0) unholdBottomPopupMenu(); 181 | else holdBottomPopMenu(); 182 | } 183 | 184 | private void changeTextByStatus(int status) { 185 | if (status == COMPRESS_STATUS_UNDO) { 186 | bottomMenuCompress.setText("压缩选中文件"); 187 | bottomMenuDecompress.setText("解压选中文件"); 188 | bottomMenuCompress.setEnabled(true); 189 | bottomMenuDecompress.setEnabled(true); 190 | } else if (status == COMPRESS_STATUS_SELECTFILES) { 191 | bottomMenuCompress.setText("压缩到此处"); 192 | bottomMenuDecompress.setText("解压选中文件"); 193 | bottomMenuCompress.setEnabled(true); 194 | bottomMenuDecompress.setEnabled(false); 195 | } else if (status == COMPRESS_STATUS_SELECTZIPFILE) { 196 | bottomMenuDecompress.setText("解压到此处"); 197 | bottomMenuCompress.setText("压缩选中文件"); 198 | bottomMenuCompress.setEnabled(false); 199 | bottomMenuDecompress.setEnabled(true); 200 | } 201 | } 202 | 203 | @Override 204 | public void onClick(final View view) { 205 | final FolderFragment folderFragment = ((FolderFragment) manager.findFragmentById(R.id.folder_fragment_layout)); 206 | switch (view.getId()) { 207 | case R.id.bottom_popup_menu_compress: 208 | if (compressStatus == COMPRESS_STATUS_UNDO) { 209 | selectedUncompressedFiles = new LinkedList<>(folderFragment.getSelectedFiles()); 210 | String str = "选中文件列表"; 211 | for (MyFile myFile : folderFragment.getSelectedFiles()) { 212 | str += (myFile.getAbsolutePath() + "\n"); 213 | } 214 | Log.d("test9", str); 215 | compressStatus = COMPRESS_STATUS_SELECTFILES; 216 | changeTextByStatus(compressStatus); 217 | break; 218 | } 219 | if ((compressStatus == COMPRESS_STATUS_SELECTFILES)) { 220 | AlertDialog.Builder builder = new AlertDialog.Builder(this); 221 | builder.setTitle("请输入压缩文件名"); 222 | final EditText edit = new EditText(this); 223 | builder.setView(edit); 224 | edit.setText(".zip"); 225 | builder.setPositiveButton("确认", new DialogInterface.OnClickListener() { 226 | @Override 227 | public void onClick(DialogInterface dialog, int which) { 228 | List fileNameList = new ArrayList<>(); 229 | for (MyFile myFile : selectedUncompressedFiles) { 230 | fileNameList.add(myFile.getAbsolutePath()); 231 | } 232 | String name = edit.getText().toString(); 233 | if (name.equals(".zip")) name = "default.zip"; 234 | if (name.length() <= 4 || name.lastIndexOf(".zip") != name.length() - 4) { 235 | name = name + ".zip"; 236 | } 237 | File file = new File(name); 238 | if (file.exists()) { 239 | Toast.makeText(MainActivity.this, "该文件已存在!", Toast.LENGTH_SHORT).show(); 240 | return; 241 | } 242 | Toast.makeText(MainActivity.this, currentAbsolutePath + "/" + name, Toast.LENGTH_SHORT).show(); 243 | 244 | fileNameList.add(currentAbsolutePath + "/" + name); 245 | FolderFragment folderFragment = (FolderFragment) manager.findFragmentById(R.id.folder_fragment_layout); 246 | new CompressTask(MainActivity.this).execute(fileNameList); 247 | toggleBottomPopupMenu(); 248 | compressStatus = COMPRESS_STATUS_UNDO; 249 | changeTextByStatus(compressStatus); 250 | } 251 | }); 252 | builder.setNegativeButton("取消", new DialogInterface.OnClickListener() { 253 | @Override 254 | public void onClick(DialogInterface dialog, int which) { 255 | 256 | } 257 | }); 258 | AlertDialog dialog = builder.create(); 259 | dialog.create(); 260 | dialog.show(); 261 | break; 262 | } 263 | 264 | break; 265 | 266 | case R.id.bottom_popup_menu_decompress: 267 | if (compressStatus == COMPRESS_STATUS_UNDO) { 268 | String str = "解压选中文件列表"; 269 | for (MyFile myFile : folderFragment.getSelectedFiles()) { 270 | str += (myFile.getAbsolutePath() + "\n"); 271 | } 272 | //Log.d("test9", str); 273 | if (folderFragment.getSelectedFiles().size() != 1 || folderFragment.getSelectedFiles().get(0).getType() != MyFile.TYPE_FILE || !folderFragment.getSelectedFiles().get(0).getAbsolutePath().matches("((\\S+(\\S|\\s)*\\S+)|\\S+)\\.zip")) { 274 | Toast.makeText(this, "请选择一个zip类型的压缩文件进行压缩!", Toast.LENGTH_SHORT).show(); 275 | break; 276 | } 277 | selectedUndecompressedFiles = new ArrayList<>(folderFragment.getSelectedFiles()); 278 | MyFile myFile = folderFragment.getSelectedFiles().get(0); 279 | compressStatus = COMPRESS_STATUS_SELECTZIPFILE; 280 | changeTextByStatus(compressStatus); 281 | break; 282 | } 283 | if (compressStatus == COMPRESS_STATUS_SELECTZIPFILE) { 284 | List nameList = new ArrayList(); 285 | nameList.add(selectedUndecompressedFiles.get(0).getAbsolutePath()); 286 | nameList.add(currentAbsolutePath + "/"); 287 | new DecompressTask(MainActivity.this).execute(nameList); 288 | toggleBottomPopupMenu(); 289 | compressStatus = COMPRESS_STATUS_UNDO; 290 | changeTextByStatus(compressStatus); 291 | 292 | } 293 | 294 | break; 295 | } 296 | } 297 | 298 | //如果底部菜单出来了,先返回底部菜单 299 | @Override 300 | public void onBackPressed() { 301 | if (bottomPopupMenuLayout.getHeight() != 0) { 302 | holdBottomPopMenu(); 303 | return; 304 | } 305 | super.onBackPressed(); 306 | 307 | } 308 | } 309 | -------------------------------------------------------------------------------- /app/src/main/java/com/zqw/fileoperation/MyApplication.java: -------------------------------------------------------------------------------- 1 | package com.zqw.fileoperation; 2 | 3 | import android.content.Context; 4 | import android.app.Application; 5 | 6 | /** 7 | * Created by 51376 on 2018/3/17. 8 | */ 9 | 10 | public class MyApplication extends Application { 11 | private static Context context; 12 | @Override 13 | public void onCreate(){ 14 | super.onCreate(); 15 | context = getApplicationContext(); 16 | } 17 | public static Context getContext() { 18 | return context; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/zqw/fileoperation/RequestPermissionActivity.java: -------------------------------------------------------------------------------- 1 | package com.zqw.fileoperation; 2 | 3 | import android.Manifest; 4 | import android.content.Intent; 5 | import android.content.pm.PackageManager; 6 | import android.support.annotation.NonNull; 7 | import android.support.v4.app.ActivityCompat; 8 | import android.support.v4.content.ContextCompat; 9 | import android.support.v7.app.AppCompatActivity; 10 | import android.os.Bundle; 11 | 12 | public class RequestPermissionActivity extends AppCompatActivity { 13 | private boolean hasPermission = false; 14 | 15 | @Override 16 | protected void onCreate(Bundle savedInstanceState) { 17 | super.onCreate(savedInstanceState); 18 | setContentView(R.layout.activity_request_permission); 19 | getPermission(); 20 | } 21 | 22 | private void getPermission() { 23 | int permissionCheck1 = ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.READ_EXTERNAL_STORAGE); 24 | int permissionCheck2 = ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE); 25 | if (permissionCheck1 != PackageManager.PERMISSION_GRANTED || permissionCheck2 != PackageManager.PERMISSION_GRANTED) { 26 | ActivityCompat.requestPermissions(this, 27 | new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, 28 | 124); 29 | } else { 30 | runMainActivity(); 31 | } 32 | } 33 | 34 | @Override 35 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 36 | //super.onRequestPermissionsResult(requestCode, permissions, grantResults); 37 | for (int g : grantResults) { 38 | if (g != PackageManager.PERMISSION_GRANTED) return; 39 | } 40 | runMainActivity(); 41 | } 42 | 43 | private void runMainActivity() { 44 | Intent intent = new Intent(this, MainActivity.class); 45 | startActivity(intent); 46 | finish(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/com/zqw/fileoperation/adapters/MyAdapter.java: -------------------------------------------------------------------------------- 1 | package com.zqw.fileoperation.adapters; 2 | 3 | import android.app.FragmentManager; 4 | import android.content.Context; 5 | import android.support.v7.widget.RecyclerView; 6 | import android.util.Log; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.CheckBox; 11 | import android.widget.CompoundButton; 12 | import android.widget.ImageView; 13 | import android.widget.TextView; 14 | 15 | 16 | import com.zqw.fileoperation.R; 17 | import com.zqw.fileoperation.fragments.FolderFragment; 18 | import com.zqw.fileoperation.pojos.MyFile; 19 | 20 | import java.util.List; 21 | 22 | /** 23 | * Created by 51376 on 2018/3/15. 24 | */ 25 | 26 | public class MyAdapter extends RecyclerView.Adapter { 27 | private FolderFragment folderFragment = null; 28 | private List myFiles = null; 29 | private Context context = null; 30 | private OnFileItemClickListener onFileItemClickListener = null; 31 | public FragmentManager manager = null; 32 | private boolean isChecked = false; 33 | 34 | public MyAdapter(List myFiles, FragmentManager fragmentManager, FolderFragment folderFragment, Context context) { 35 | this.myFiles = myFiles; 36 | this.manager = fragmentManager; 37 | this.folderFragment = folderFragment; 38 | this.context = context; 39 | } 40 | 41 | @Override 42 | public ViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) { 43 | Log.d("test11", "oncreate"); 44 | View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.file_item, parent, false); 45 | final ViewHolder holder = new ViewHolder(view); 46 | 47 | view.setOnClickListener(new View.OnClickListener() { 48 | @Override 49 | public void onClick(View view) { 50 | int position = holder.getAdapterPosition(); 51 | onFileItemClickListener.onItemClick(view, position); 52 | } 53 | }); 54 | view.setOnLongClickListener(new View.OnLongClickListener() { 55 | @Override 56 | public boolean onLongClick(View view) { 57 | int position = holder.getAdapterPosition(); 58 | onFileItemClickListener.onItemLongClick(view, position); 59 | return true; 60 | } 61 | }); 62 | holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 63 | @Override 64 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 65 | int position = holder.getAdapterPosition(); 66 | onFileItemClickListener.onCheckedChange(buttonView, isChecked, myFiles.get(position)); 67 | } 68 | }); 69 | return holder; 70 | } 71 | 72 | @Override 73 | public void onBindViewHolder(ViewHolder holder, int position) { 74 | MyFile myFile = myFiles.get(position); 75 | holder.fileName.setText(myFile.getFileName()); 76 | holder.fileDescribe.setText(myFile.getFileDescribe()); 77 | if (myFile.getType() == 0) 78 | holder.thumbnail.setBackgroundResource(R.drawable.folder2); 79 | else if (myFile.getType() == 1) { 80 | holder.thumbnail.setBackgroundResource(R.drawable.file1); 81 | } 82 | if (isChecked) 83 | holder.checkBox.setVisibility(View.VISIBLE); 84 | else holder.checkBox.setVisibility(View.GONE); 85 | } 86 | 87 | @Override 88 | public int getItemCount() { 89 | return myFiles.size(); 90 | } 91 | 92 | class ViewHolder extends RecyclerView.ViewHolder { 93 | TextView fileName; 94 | TextView fileDescribe; 95 | ImageView thumbnail; 96 | CheckBox checkBox; 97 | 98 | public ViewHolder(View view) { 99 | super(view); 100 | fileName = (TextView) view.findViewById(R.id.file_name); 101 | fileDescribe = (TextView) view.findViewById(R.id.file_describe); 102 | thumbnail = (ImageView) view.findViewById(R.id.file_thumbnail); 103 | checkBox = (CheckBox) view.findViewById(R.id.file_item_checkBox); 104 | checkBox.setVisibility(View.GONE); 105 | } 106 | } 107 | 108 | public void setOnFileItemClickListener(OnFileItemClickListener onFileItemClickListener) { 109 | this.onFileItemClickListener = onFileItemClickListener; 110 | } 111 | 112 | public boolean isChecked() { 113 | return isChecked; 114 | } 115 | 116 | public void setChecked(boolean checked) { 117 | isChecked = checked; 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /app/src/main/java/com/zqw/fileoperation/adapters/OnFileItemClickListener.java: -------------------------------------------------------------------------------- 1 | package com.zqw.fileoperation.adapters; 2 | 3 | import android.view.View; 4 | import android.widget.CompoundButton; 5 | 6 | import com.zqw.fileoperation.pojos.MyFile; 7 | 8 | /** 9 | * Created by 51376 on 2018/4/19. 10 | */ 11 | 12 | public interface OnFileItemClickListener { 13 | void onItemClick(View view, int position); 14 | 15 | void onItemLongClick(View view, int position); 16 | 17 | void onCheckedChange(CompoundButton buttonView, boolean isChecked, MyFile myFile); 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/zqw/fileoperation/adapters/OnItemClickListener.java: -------------------------------------------------------------------------------- 1 | package com.zqw.fileoperation.adapters; 2 | 3 | import android.view.View; 4 | import android.widget.CompoundButton; 5 | 6 | import com.zqw.fileoperation.pojos.MyFile; 7 | 8 | /** 9 | * Created by 51376 on 2018/3/19. 10 | */ 11 | 12 | public interface OnItemClickListener { 13 | 14 | void onItemClick(View view, int position); 15 | 16 | } 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/zqw/fileoperation/adapters/PreviewBarAdapter.java: -------------------------------------------------------------------------------- 1 | package com.zqw.fileoperation.adapters; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.util.Log; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.TextView; 9 | 10 | import com.zqw.fileoperation.R; 11 | 12 | import java.util.List; 13 | 14 | /** 15 | * Created by 51376 on 2018/3/19. 16 | */ 17 | 18 | public class PreviewBarAdapter extends RecyclerView.Adapter { 19 | 20 | public List previewBarItems = null; 21 | private OnItemClickListener onItemClickListener = null; 22 | 23 | public PreviewBarAdapter(List previewBarItems) { 24 | this.previewBarItems = previewBarItems; 25 | } 26 | 27 | @Override 28 | public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 29 | final View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.preview_bar_item_layout, parent, false); 30 | final ViewHolder viewHolder = new ViewHolder(view); 31 | view.setOnClickListener(new View.OnClickListener() { 32 | @Override 33 | public void onClick(View v) { 34 | onItemClickListener.onItemClick(v,viewHolder.getAdapterPosition()); 35 | } 36 | }); 37 | return viewHolder; 38 | } 39 | 40 | @Override 41 | public void onBindViewHolder(ViewHolder holder, int position) { 42 | String path = previewBarItems.get(position); 43 | if (position == 0) path = "内部储存"; 44 | else { 45 | int index = path.lastIndexOf("/"); 46 | if (index > 0 && path.length() - index > 1) { 47 | path = path.substring(index + 1, path.length()); 48 | if (path.length() > 10) path = path.substring(0, 10) + "..."; 49 | } 50 | } 51 | holder.path.setText(path); 52 | } 53 | 54 | @Override 55 | public int getItemCount() { 56 | return previewBarItems.size(); 57 | } 58 | 59 | public void setOnItemClickListener(OnItemClickListener onItemClickListener) { 60 | this.onItemClickListener = onItemClickListener; 61 | } 62 | 63 | class ViewHolder extends RecyclerView.ViewHolder { 64 | TextView path; 65 | 66 | public ViewHolder(View view) { 67 | super(view); 68 | path = (TextView) view.findViewById(R.id.preview_bar_item_path); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /app/src/main/java/com/zqw/fileoperation/fragments/FolderFragment.java: -------------------------------------------------------------------------------- 1 | package com.zqw.fileoperation.fragments; 2 | 3 | import android.animation.ValueAnimator; 4 | import android.app.AlertDialog; 5 | import android.app.Fragment; 6 | import android.app.FragmentManager; 7 | import android.app.FragmentTransaction; 8 | import android.content.Context; 9 | import android.content.DialogInterface; 10 | import android.os.Bundle; 11 | import android.support.v7.widget.DividerItemDecoration; 12 | import android.support.v7.widget.LinearLayoutManager; 13 | import android.support.v7.widget.RecyclerView; 14 | import android.util.Log; 15 | import android.view.LayoutInflater; 16 | import android.view.View; 17 | import android.view.ViewGroup; 18 | import android.widget.CompoundButton; 19 | 20 | import com.zqw.fileoperation.MainActivity; 21 | import com.zqw.fileoperation.adapters.MyAdapter; 22 | import com.zqw.fileoperation.R; 23 | import com.zqw.fileoperation.adapters.OnFileItemClickListener; 24 | import com.zqw.fileoperation.adapters.OnItemClickListener; 25 | import com.zqw.fileoperation.functions.FileFounder; 26 | import com.zqw.fileoperation.pojos.MyFile; 27 | 28 | import java.util.LinkedList; 29 | import java.util.List; 30 | 31 | /** 32 | * Created by 51376 on 2018/3/15. 33 | */ 34 | public class FolderFragment extends Fragment { 35 | 36 | private RecyclerView recyclerView = null; 37 | private List myFiles = new LinkedList<>(); 38 | private FragmentManager manager = null; 39 | private View view; 40 | private String absolutePath = "/storage/emulated/0"; 41 | public MyAdapter adapter = null; 42 | private MainActivity mainActivity = null; 43 | private List selectedFiles = new LinkedList<>(); 44 | 45 | 46 | private LinearLayoutManager linearLayoutManager = null; 47 | 48 | public RecyclerView getRecyclerView() { 49 | return recyclerView; 50 | } 51 | 52 | public void setRecyclerView(RecyclerView recyclerView) { 53 | this.recyclerView = recyclerView; 54 | } 55 | 56 | public String getAbsolutePath() { 57 | return absolutePath; 58 | } 59 | 60 | public void setAbsolutePath(String absolutePath) { 61 | this.absolutePath = absolutePath; 62 | } 63 | 64 | //在onAttach内获取活动的实例 65 | @Override 66 | public void onAttach(Context context) { 67 | super.onAttach(context); 68 | mainActivity = (MainActivity) getActivity(); 69 | } 70 | 71 | @Override 72 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 73 | View view = inflater.inflate(R.layout.folder_fragment, container, false); 74 | this.view = view; 75 | return view; 76 | } 77 | 78 | @Override 79 | public void onStart() { 80 | super.onStart(); 81 | recyclerView = (RecyclerView) view.findViewById(R.id.recycler_view); 82 | linearLayoutManager = new LinearLayoutManager(getActivity()); 83 | recyclerView.setLayoutManager(linearLayoutManager); 84 | recyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL)); 85 | myFiles = FileFounder.getFilesFromDir(absolutePath, getActivity()); 86 | if (myFiles == null) { 87 | myFiles = new LinkedList<>(); 88 | //读取不出来的情况 89 | } 90 | //装配适配器,在里面实现点击事件的回调 91 | recyclerViewAdpterAssemble(); 92 | mainActivity.currentAbsolutePath = absolutePath; 93 | } 94 | 95 | //刷新列表(整体刷新) 96 | public void onRefresh() { 97 | myFiles = FileFounder.getFilesFromDir(absolutePath, getActivity()); 98 | if (myFiles == null) { 99 | myFiles = new LinkedList<>(); 100 | //读取不出来的情况 101 | } 102 | // myFiles. 103 | recyclerViewAdpterAssemble(); 104 | } 105 | 106 | //实现点击,长按事件的回调 107 | private void recyclerViewAdpterAssemble() { 108 | //每次刷新重置选中列表 109 | selectedFiles.clear(); 110 | adapter = new MyAdapter(myFiles, getActivity().getFragmentManager(), this, getActivity()); 111 | adapter.setOnFileItemClickListener(new OnFileItemClickListener() { 112 | @Override 113 | public void onItemClick(View view, int position) { 114 | MyFile myFile = myFiles.get(position); 115 | int a = 10; 116 | //所点击为目录的情况 117 | if (myFile.getType() == 0) { 118 | //Toast.makeText(context, myFile.getAbsolutePath(), Toast.LENGTH_SHORT).show(); 119 | //读取不出来的情况 120 | if (FileFounder.getFilesFromDir(myFile.getAbsolutePath(), getActivity()) == null) { 121 | AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); 122 | builder.setTitle("目录无法打开!"); 123 | builder.setMessage("该目录无法打开或者已经损坏"); 124 | builder.setPositiveButton("确定", new DialogInterface.OnClickListener() { 125 | @Override 126 | public void onClick(DialogInterface dialogInterface, int i) { 127 | } 128 | }); 129 | builder.show(); 130 | return; 131 | } 132 | manager = getFragmentManager(); 133 | FragmentTransaction transaction = manager.beginTransaction(); 134 | FolderFragment newfolderfragment = new FolderFragment(); 135 | //为新的文件夹碎片设置路径 136 | newfolderfragment.setAbsolutePath(myFile.getAbsolutePath()); 137 | FolderFragment oldfolderfragment = (FolderFragment) manager.findFragmentById(R.id.folder_fragment_layout); 138 | transaction.remove(oldfolderfragment); 139 | transaction.add(R.id.folder_fragment_layout, newfolderfragment); 140 | //transaction.replace(R.id.folder_fragment_layout, newfolderfragment); 141 | transaction.addToBackStack(null); 142 | transaction.commit(); 143 | } 144 | } 145 | 146 | //长按文件事件 147 | @Override 148 | public void onItemLongClick(View view, int position) { 149 | mainActivity.onItemLongClick(position); 150 | } 151 | 152 | @Override 153 | public void onCheckedChange(CompoundButton buttonView, boolean isChecked, MyFile myFile) { 154 | if (isChecked) { 155 | if (!selectedFiles.contains(myFile)) 156 | selectedFiles.add(myFile); 157 | } else { 158 | if (selectedFiles.contains(myFile)) 159 | selectedFiles.remove(myFile); 160 | } 161 | } 162 | }); 163 | recyclerView.setAdapter(adapter); 164 | } 165 | 166 | public LinearLayoutManager getLinearLayoutManager() { 167 | return linearLayoutManager; 168 | } 169 | 170 | public List getSelectedFiles() { 171 | return selectedFiles; 172 | } 173 | 174 | } 175 | 176 | -------------------------------------------------------------------------------- /app/src/main/java/com/zqw/fileoperation/functions/FileFounder.java: -------------------------------------------------------------------------------- 1 | package com.zqw.fileoperation.functions; 2 | 3 | import android.content.Context; 4 | 5 | import com.zqw.fileoperation.pojos.MyFile; 6 | 7 | import java.io.File; 8 | import java.util.LinkedList; 9 | import java.util.List; 10 | 11 | /** 12 | * Created by 51376 on 2018/3/16. 13 | */ 14 | 15 | public class FileFounder { 16 | private FileFounder() { 17 | } 18 | 19 | public static List getFilesFromDir(String path, Context context) { 20 | File file = new File(path); 21 | if (!file.exists() || !file.isDirectory()) { 22 | // Toast.makeText(context, "路径不存在或已经被删除!", Toast.LENGTH_SHORT).show(); 23 | return null; 24 | } 25 | // //test 26 | // if(file.getName().contains("data")){ 27 | // return null; 28 | // } 29 | // //test 30 | List myFiles = new LinkedList<>(); 31 | File[] subFiles = file.listFiles(); 32 | for (File subFile : subFiles) { 33 | MyFile myFile = new MyFile(); 34 | String subFileName = subFile.getName(); 35 | if (subFileName.length() > 30) { 36 | subFileName = subFileName.substring(0, 30); 37 | subFileName = subFileName + "..."; 38 | } 39 | myFile.setFileName(subFileName); 40 | myFile.setAbsolutePath(subFile.getAbsolutePath()); 41 | if (subFile.isDirectory()) { 42 | myFile.setFileDescribe("目录"); 43 | myFile.setType(MyFile.TYPE_DIR); 44 | } else { 45 | myFile.setFileDescribe("文件"); 46 | myFile.setType(MyFile.TYPE_FILE); 47 | } 48 | myFiles.add(myFile); 49 | } 50 | return myFiles; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /app/src/main/java/com/zqw/fileoperation/functions/MyCompress.java: -------------------------------------------------------------------------------- 1 | package com.zqw.fileoperation.functions; 2 | 3 | /** 4 | * Created by 51376 on 2018/4/19. 5 | */ 6 | 7 | import com.zqw.fileoperation.tasks.CompressTask; 8 | import com.zqw.fileoperation.tasks.DecompressTask; 9 | 10 | import java.io.BufferedInputStream; 11 | import java.io.BufferedOutputStream; 12 | import java.io.File; 13 | import java.io.FileInputStream; 14 | import java.io.FileOutputStream; 15 | import java.io.IOException; 16 | import java.util.LinkedList; 17 | import java.util.List; 18 | import java.util.zip.ZipEntry; 19 | import java.util.zip.ZipInputStream; 20 | import java.util.zip.ZipOutputStream; 21 | 22 | public class MyCompress { 23 | 24 | private volatile static boolean isCancelled = false; 25 | 26 | public static void setCancelled(boolean cancelled) { 27 | isCancelled = cancelled; 28 | } 29 | 30 | //filePathes列表最后一个为压缩文件路径 31 | public static boolean execCompress(List filePathes, CompressTask compressTask) { 32 | String zipFilePath = filePathes.get(filePathes.size() - 1); 33 | filePathes.remove(filePathes.size() - 1); 34 | ZipOutputStream zipOutputStream = null; 35 | BufferedOutputStream bufferedOutputStream = null; 36 | try { 37 | File file1 = new File(zipFilePath); 38 | if (file1.exists()) throw new Exception(); 39 | zipOutputStream = new ZipOutputStream(new FileOutputStream(zipFilePath)); 40 | bufferedOutputStream = new BufferedOutputStream(zipOutputStream, 1048576); 41 | for (String sourceFilePath : filePathes) { 42 | if (isCancelled) throw new Exception("cancel"); 43 | File file = new File(sourceFilePath); 44 | compress(zipOutputStream, bufferedOutputStream, file, "", compressTask); 45 | } 46 | return true; 47 | } catch (Exception e) { 48 | File file = new File(zipFilePath); 49 | if (file.exists()) file.delete(); 50 | e.printStackTrace(); 51 | return false; 52 | } finally { 53 | isCancelled = false; 54 | try { 55 | if (bufferedOutputStream != null) 56 | bufferedOutputStream.close(); 57 | } catch (IOException e) { 58 | e.printStackTrace(); 59 | } 60 | } 61 | } 62 | 63 | public static boolean execDecompress(List list, DecompressTask decompressTask) { 64 | String sourceZipFileName = list.get(0); 65 | String DestFilePath = list.get(1); 66 | System.out.println("源文件和目的文件" + sourceZipFileName + " " + DestFilePath); 67 | ZipInputStream zipInputStream = null; 68 | try { 69 | zipInputStream = new ZipInputStream(new BufferedInputStream(new FileInputStream(sourceZipFileName))); 70 | ZipEntry entry; 71 | while ((entry = zipInputStream.getNextEntry()) != null) { 72 | if (isCancelled) throw new Exception(); 73 | BufferedOutputStream bufferedOutputStream = null; 74 | try { 75 | decompressTask.publishDecompressProgress(entry.getName() + entry.getName().lastIndexOf("/")); 76 | int lastIndex = entry.getName().lastIndexOf("/"); 77 | String preFixPath = "/"; 78 | if (lastIndex != -1) { 79 | preFixPath = entry.getName().substring(0, entry.getName().lastIndexOf("/") + 1); 80 | File file = new File(DestFilePath + preFixPath); 81 | if (!file.exists()) new File(DestFilePath + preFixPath).mkdirs(); 82 | } 83 | if (entry.isDirectory()) { 84 | continue; 85 | } 86 | bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(DestFilePath + entry.getName()), 1048576); 87 | int count; 88 | byte[] bytes = new byte[1048576]; 89 | while ((count = zipInputStream.read(bytes, 0, 1048576)) != -1) { 90 | bufferedOutputStream.write(bytes, 0, count); 91 | } 92 | bufferedOutputStream.flush(); 93 | } catch (Exception e) { 94 | e.printStackTrace(); 95 | return false; 96 | } finally { 97 | isCancelled = false; 98 | if (bufferedOutputStream != null) 99 | bufferedOutputStream.close(); 100 | } 101 | } 102 | } catch (Exception e) { 103 | e.printStackTrace(); 104 | return false; 105 | } finally { 106 | try { 107 | zipInputStream.close(); 108 | } catch (IOException e) { 109 | e.printStackTrace(); 110 | } 111 | } 112 | return true; 113 | } 114 | 115 | private static void compress(ZipOutputStream out, BufferedOutputStream bufferedOutputStream, File sourceFile, String base, CompressTask compressTask) throws Exception { 116 | if (isCancelled) throw new Exception("cancel"); 117 | if (sourceFile.isDirectory()) { 118 | File[] files = sourceFile.listFiles(); 119 | if (files.length == 0) { 120 | out.putNextEntry(new ZipEntry(base + sourceFile.getName() + "/")); 121 | } else { 122 | for (File file : files) { 123 | compress(out, bufferedOutputStream, file, base + sourceFile.getName() + "/", compressTask); 124 | } 125 | } 126 | } else { 127 | compressTask.publishCompressProgress(sourceFile.getAbsolutePath()); 128 | BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(sourceFile)); 129 | out.putNextEntry(new ZipEntry(base + sourceFile.getName())); 130 | int tag; 131 | while ((tag = bufferedInputStream.read()) != -1) { 132 | // out.write(tag); 133 | bufferedOutputStream.write(tag); 134 | //flush之后才能真正写入磁盘 135 | bufferedOutputStream.flush(); 136 | } 137 | bufferedInputStream.close(); 138 | } 139 | } 140 | 141 | public static void test() { 142 | 143 | File file = new File("newfolder1"); 144 | // String src = file.getAbsolutePath(); 145 | String src1 = "C:\\Users\\51376\\IdeaProjects\\CSPTest\\tt1.pdf"; 146 | String src2 = "C:\\Users\\51376\\IdeaProjects\\CSPTest\\pic1.jpg"; 147 | String src3 = "C:\\Users\\51376\\IdeaProjects\\CSPTest\\pic2.jpg"; 148 | String src4 = "C:\\Users\\51376\\IdeaProjects\\CSPTest\\newfolder1"; 149 | String src5 = "C:\\Users\\51376\\IdeaProjects\\CSPTest\\emptyfolder"; 150 | List list = new LinkedList<>(); 151 | list.add(src1); 152 | list.add(src2); 153 | list.add(src3); 154 | list.add(src4); 155 | //String src = "C:\\Users\\51376\\IdeaProjects\\CSPTest\\tt1.pdf"; 156 | String srcZip = "C:\\Users\\51376\\IdeaProjects\\CSPTest\\Mutil4.zip"; 157 | String destPath = "C:/Users/51376/IdeaProjects/CSPTest/mypotplayer/"; 158 | String srcPath = "C:/Users/51376/IdeaProjects/CSPTest/PotPlayer"; 159 | String destPath1 = "C:/Users/51376/IdeaProjects/CSPTest/Clion.zip"; 160 | // // String dest = "second1.zip"; 161 | // execCompress(list, dest); 162 | //execCompress(srcPath, destPath1); 163 | //execDecompress(destPath1, destPath); 164 | 165 | 166 | } 167 | 168 | public static void main(String[] args) throws Exception { 169 | test(); 170 | } 171 | 172 | public static void test1() { 173 | File file = new File("C:/Users/51376/IdeaProjects/CSPTest/mypotplayer"); 174 | System.out.println(file.exists()); 175 | } 176 | 177 | } 178 | -------------------------------------------------------------------------------- /app/src/main/java/com/zqw/fileoperation/functions/RandomNameGenerater.java: -------------------------------------------------------------------------------- 1 | package com.zqw.fileoperation.functions; 2 | 3 | /** 4 | * Created by 51376 on 2018/3/16. 5 | */ 6 | 7 | import java.util.Random; 8 | 9 | public class RandomNameGenerater { 10 | static String none_after_a = "yko"; 11 | static char[] vowels = {'a', 'e', 'i', 'o', 'u'}; 12 | static char[] cosonants = {'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z'}; 13 | 14 | public String getName() { 15 | StringBuilder stringBuilder = new StringBuilder(); 16 | Random random = new Random(); 17 | int digits = Math.abs(random.nextInt()) % 11 + 3; 18 | int vowelflag = 0, consonantflag = 0; 19 | char lastletter = '.'; 20 | for (int i = 0; i < digits; i++) { 21 | int type = -1; 22 | boolean ok = false; 23 | char letter = ' '; 24 | while (!ok) { 25 | if (vowelflag != 2 &&(consonantflag == 2 || Math.abs(random.nextInt(100)) < 38)) { 26 | letter = vowels[random.nextInt(5)]; 27 | type = 0; 28 | } else { 29 | letter = cosonants[random.nextInt(21)]; 30 | type = 1; 31 | } 32 | if (lastletter == 'a') { 33 | if(none_after_a.contains(String.valueOf(letter))){ 34 | break; 35 | } 36 | } 37 | lastletter = letter; 38 | ok = true; 39 | if(type == 0) vowelflag++; 40 | if(type == 1) consonantflag++; 41 | } 42 | 43 | stringBuilder.append(letter); 44 | } 45 | return stringBuilder.toString(); 46 | } 47 | 48 | private static int judge(char s) { 49 | for (char i : vowels) { 50 | if (s == i) { 51 | return 1; 52 | } 53 | } 54 | for (char i : cosonants) { 55 | if (s == i) { 56 | return 0; 57 | } 58 | } 59 | return -1; 60 | } 61 | 62 | boolean isVowelLetter(char s) { 63 | String vowels = "aeiou"; 64 | String str = String.valueOf(s); 65 | if (str.contains(vowels)) return true; 66 | return false; 67 | } 68 | } 69 | 70 | -------------------------------------------------------------------------------- /app/src/main/java/com/zqw/fileoperation/pojos/MyFile.java: -------------------------------------------------------------------------------- 1 | package com.zqw.fileoperation.pojos; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Created by 51376 on 2018/3/16. 7 | */ 8 | 9 | public class MyFile implements Serializable{ 10 | private String fileName; 11 | private String fileDescribe; 12 | private int type; 13 | private String absolutePath; 14 | private long size; 15 | 16 | public static int TYPE_FILE = 1; 17 | public static int TYPE_DIR = 0; 18 | public int getType() { 19 | return type; 20 | } 21 | 22 | public void setType(int type) { 23 | this.type = type; 24 | } 25 | 26 | public String getAbsolutePath() { 27 | return absolutePath; 28 | } 29 | 30 | public void setAbsolutePath(String absolutePath) { 31 | this.absolutePath = absolutePath; 32 | } 33 | 34 | public long getSize() { 35 | return size; 36 | } 37 | 38 | public void setSize(long size) { 39 | this.size = size; 40 | } 41 | 42 | 43 | public String getFileName() { 44 | return fileName; 45 | } 46 | 47 | public void setFileName(String fileName) { 48 | this.fileName = fileName; 49 | } 50 | 51 | public String getFileDescribe() { 52 | return fileDescribe; 53 | } 54 | 55 | public void setFileDescribe(String fileDescribe) { 56 | this.fileDescribe = fileDescribe; 57 | } 58 | 59 | //绝对路径相同认为是同一个文件 60 | @Override 61 | public boolean equals(Object obj) { 62 | if (((MyFile) obj).getAbsolutePath().equals(absolutePath)) { 63 | return true; 64 | } 65 | return false; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /app/src/main/java/com/zqw/fileoperation/tasks/CompressTask.java: -------------------------------------------------------------------------------- 1 | package com.zqw.fileoperation.tasks; 2 | 3 | import android.app.Notification; 4 | import android.app.NotificationManager; 5 | import android.app.ProgressDialog; 6 | import android.content.Context; 7 | import android.content.DialogInterface; 8 | import android.content.Intent; 9 | import android.graphics.BitmapFactory; 10 | import android.os.AsyncTask; 11 | import android.util.Log; 12 | import android.widget.Toast; 13 | 14 | import com.zqw.fileoperation.MainActivity; 15 | import com.zqw.fileoperation.MyApplication; 16 | import com.zqw.fileoperation.R; 17 | import com.zqw.fileoperation.fragments.FolderFragment; 18 | import com.zqw.fileoperation.functions.MyCompress; 19 | 20 | import java.util.List; 21 | 22 | /** 23 | * Created by 51376 on 2018/4/20. 24 | */ 25 | 26 | public class CompressTask extends AsyncTask, String, Boolean> { 27 | 28 | private ProgressDialog progressDialog = null; 29 | private MainActivity mainActivity = null; 30 | 31 | public CompressTask(final MainActivity mainActivity) { 32 | this.mainActivity = mainActivity; 33 | progressDialog = new ProgressDialog(mainActivity); 34 | progressDialog.setTitle("压缩中..."); 35 | progressDialog.setCanceledOnTouchOutside(false); 36 | progressDialog.setCancelable(true); 37 | progressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() { 38 | @Override 39 | public void onCancel(DialogInterface dialog) { 40 | MyCompress.setCancelled(true); 41 | Toast.makeText(mainActivity, "你取消了压缩", Toast.LENGTH_SHORT).show(); 42 | } 43 | }); 44 | } 45 | 46 | @Override 47 | protected void onPreExecute() { 48 | progressDialog.show(); 49 | } 50 | 51 | @Override 52 | protected void onPostExecute(Boolean result) { 53 | progressDialog.dismiss(); 54 | if (result) { 55 | Toast.makeText(mainActivity, "压缩成功!", Toast.LENGTH_SHORT).show(); 56 | mainActivity.reFresh(false); 57 | 58 | } else { 59 | Toast.makeText(mainActivity, "压缩失败!", Toast.LENGTH_SHORT).show(); 60 | } 61 | 62 | } 63 | 64 | @Override 65 | protected void onProgressUpdate(String... files) { 66 | String file = files[0]; 67 | progressDialog.setMessage("压缩:\n" + file); 68 | } 69 | 70 | @Override 71 | protected Boolean doInBackground(List[] lists) { 72 | // return true; 73 | return MyCompress.execCompress(lists[0], this); 74 | } 75 | 76 | public void publishCompressProgress(String file) { 77 | publishProgress(file); 78 | } 79 | 80 | private NotificationManager getNotificationManager() { 81 | return (NotificationManager) MyApplication.getContext().getSystemService(Context.NOTIFICATION_SERVICE); 82 | } 83 | 84 | private Notification getNotification(String title, int progress) { 85 | Notification.Builder builder = new Notification.Builder(MyApplication.getContext()). 86 | setContentTitle(title).setSmallIcon(R.mipmap.ic_launcher). 87 | setLargeIcon(BitmapFactory.decodeResource(MyApplication.getContext().getResources(), R.mipmap.ic_launcher)); 88 | if (progress > 0) { 89 | builder.setContentText("压缩进度" + progress + "%"); 90 | builder.setProgress(100, progress, false); 91 | } 92 | return builder.build(); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /app/src/main/java/com/zqw/fileoperation/tasks/DecompressTask.java: -------------------------------------------------------------------------------- 1 | package com.zqw.fileoperation.tasks; 2 | 3 | import android.app.ProgressDialog; 4 | import android.content.DialogInterface; 5 | import android.os.AsyncTask; 6 | import android.widget.Toast; 7 | 8 | import com.zqw.fileoperation.MainActivity; 9 | import com.zqw.fileoperation.functions.MyCompress; 10 | 11 | import java.util.List; 12 | 13 | /** 14 | * Created by 51376 on 2018/4/20. 15 | */ 16 | 17 | public class DecompressTask extends AsyncTask, String, Boolean> { 18 | private ProgressDialog progressDialog = null; 19 | private MainActivity mainActivity = null; 20 | 21 | public DecompressTask(final MainActivity mainActivity) { 22 | this.mainActivity = mainActivity; 23 | progressDialog = new ProgressDialog(mainActivity); 24 | progressDialog.setTitle("解压中..."); 25 | progressDialog.setCanceledOnTouchOutside(false); 26 | progressDialog.setCancelable(true); 27 | progressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() { 28 | @Override 29 | public void onCancel(DialogInterface dialog) { 30 | MyCompress.setCancelled(true); 31 | Toast.makeText(mainActivity, "你取消了解压", Toast.LENGTH_SHORT).show(); 32 | } 33 | }); 34 | } 35 | 36 | @Override 37 | protected void onPreExecute() { 38 | progressDialog.show(); 39 | } 40 | 41 | @Override 42 | protected void onPostExecute(Boolean result) { 43 | progressDialog.dismiss(); 44 | if (result) { 45 | Toast.makeText(mainActivity, "解压成功!", Toast.LENGTH_SHORT).show(); 46 | mainActivity.reFresh(false); 47 | 48 | } else { 49 | Toast.makeText(mainActivity, "解压失败!", Toast.LENGTH_SHORT).show(); 50 | } 51 | } 52 | 53 | @Override 54 | protected void onProgressUpdate(String... files) { 55 | String file = files[0]; 56 | progressDialog.setMessage("提取:\n" + file); 57 | } 58 | 59 | @Override 60 | protected Boolean doInBackground(List[] lists) { 61 | return MyCompress.execDecompress(lists[0], this); 62 | } 63 | 64 | public void publishDecompressProgress(String file) { 65 | publishProgress(file); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /app/src/main/java/com/zqw/fileoperation/tasks/FilePathTask.java: -------------------------------------------------------------------------------- 1 | package com.zqw.fileoperation.tasks; 2 | 3 | import android.os.AsyncTask; 4 | import android.provider.ContactsContract; 5 | 6 | /** 7 | * Created by 51376 on 2018/3/16. 8 | */ 9 | 10 | //public class FilePathTask extends AsyncTask { 11 | //} 12 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bottom_menu_border.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/download_list_parentitem.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/file1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CanisMajorXI/AndroidFileManager/a965161a564f24606c1355359953312b29403c01/app/src/main/res/drawable/file1.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/folder1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CanisMajorXI/AndroidFileManager/a965161a564f24606c1355359953312b29403c01/app/src/main/res/drawable/folder1.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/folder2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CanisMajorXI/AndroidFileManager/a965161a564f24606c1355359953312b29403c01/app/src/main/res/drawable/folder2.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/myborder.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/selected_ripple.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/test1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_filelist.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 10 | 11 |