diff --git a/app/build.gradle b/app/build.gradle index 6d6317e..f08fdc8 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -5,7 +5,7 @@ android { buildToolsVersion "23.0.2" defaultConfig { - applicationId "com.csc.lesson5" + applicationId "ru.ppzh.filemanager" minSdkVersion 15 targetSdkVersion 23 versionCode 1 @@ -21,4 +21,5 @@ android { dependencies { compile 'com.android.support:appcompat-v7:23.2.1' + compile 'com.android.support:recyclerview-v7:23.2.1' } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 6296c85..5b2df16 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,6 +1,8 @@ + package="ru.ppzh.filemanager"> + + - + + diff --git a/app/src/main/java/com/csc/lesson5/MainActivity.java b/app/src/main/java/com/csc/lesson5/MainActivity.java deleted file mode 100644 index 613d372..0000000 --- a/app/src/main/java/com/csc/lesson5/MainActivity.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.csc.lesson5; - -import android.support.v7.app.AppCompatActivity; -import android.os.Bundle; - -public class MainActivity extends AppCompatActivity { - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } -} diff --git a/app/src/main/java/ru/ppzh/filemanager/ImageLoader.java b/app/src/main/java/ru/ppzh/filemanager/ImageLoader.java new file mode 100644 index 0000000..f2d7214 --- /dev/null +++ b/app/src/main/java/ru/ppzh/filemanager/ImageLoader.java @@ -0,0 +1,41 @@ +package ru.ppzh.filemanager; + +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; + +public class ImageLoader { + + public Bitmap decodeSampledBitmapFromFile(String path, int reqWidth, int reqHeight) { + + final BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + BitmapFactory.decodeFile(path, options); + + options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); + + options.inJustDecodeBounds = false; + return BitmapFactory.decodeFile(path, options); + } + + public int calculateInSampleSize( + BitmapFactory.Options options, int reqWidth, int reqHeight) { + + final int height = options.outHeight; + final int width = options.outWidth; + int inSampleSize = 1; + + if (height > reqHeight || width > reqWidth) { + + final int halfHeight = height / 2; + final int halfWidth = width / 2; + + + while ((halfHeight / inSampleSize) > reqHeight + && (halfWidth / inSampleSize) > reqWidth) { + inSampleSize *= 2; + } + } + + return inSampleSize; + } +} diff --git a/app/src/main/java/ru/ppzh/filemanager/ImageViewer.java b/app/src/main/java/ru/ppzh/filemanager/ImageViewer.java new file mode 100644 index 0000000..df8ce42 --- /dev/null +++ b/app/src/main/java/ru/ppzh/filemanager/ImageViewer.java @@ -0,0 +1,31 @@ +package ru.ppzh.filemanager; + +import android.graphics.Bitmap; +import android.graphics.Point; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.view.Display; +import android.widget.ImageView; + +public class ImageViewer extends AppCompatActivity { + private ImageView imageView; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.image_viewer); + imageView = (ImageView) findViewById(R.id.image_viewer); + + ImageLoader imageloader = new ImageLoader(); + String imagePath = getIntent().getStringExtra(MainActivity.IMAGE_PATH); + Display display = getWindowManager().getDefaultDisplay(); + Point size = new Point(); + display.getSize(size); + Bitmap image = imageloader.decodeSampledBitmapFromFile( + imagePath, + size.x, + size.y + ); + imageView.setImageBitmap(image); + } +} diff --git a/app/src/main/java/ru/ppzh/filemanager/Item.java b/app/src/main/java/ru/ppzh/filemanager/Item.java new file mode 100644 index 0000000..67aa6a6 --- /dev/null +++ b/app/src/main/java/ru/ppzh/filemanager/Item.java @@ -0,0 +1,97 @@ +package ru.ppzh.filemanager; + + +import android.graphics.Bitmap; +import android.support.annotation.NonNull; +import android.util.Log; + +public class Item implements Comparable { + public static final String TAG = "Item"; + + private String name; + private String date; + private String path; + private Bitmap preview; + private boolean isDirectory; + + public Item(String name, String date, String path, Bitmap preview, boolean isDirectory) { + this.name = name; + this.date = date; + this.path = path; + this.preview = preview; + this.isDirectory = isDirectory; + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setDate(String date) { + this.date = date; + } + + public String getDate() { + return date; + } + + public void setPath(String path) { + this.path = path; + } + + public String getPath() { + return path; + } + + public Bitmap getPreview() { + return preview; + } + + public boolean isDirectory() { + return isDirectory; + } + + public int compareTo(@NonNull Item o) { + if (this.name != null) + return this.name.toLowerCase().compareTo(o.getName().toLowerCase()); + else + throw new IllegalArgumentException(); + } + + public String getExtension() { + int index = name.lastIndexOf('.'); + String extension = name.substring(index); + + Log.i(TAG, extension); + + return extension; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Item)) return false; + + Item item = (Item) o; + + if (isDirectory() != item.isDirectory()) return false; + if (!getName().equals(item.getName())) return false; + if (!getDate().equals(item.getDate())) return false; + if (!getPath().equals(item.getPath())) return false; + return getPreview().equals(item.getPreview()); + + } + + @Override + public int hashCode() { + int result = getName().hashCode(); + result = 31 * result + getDate().hashCode(); + result = 31 * result + getPath().hashCode(); + result = 31 * result + getPreview().hashCode(); + result = 31 * result + (isDirectory() ? 1 : 0); + return result; + } +} \ No newline at end of file diff --git a/app/src/main/java/ru/ppzh/filemanager/MainActivity.java b/app/src/main/java/ru/ppzh/filemanager/MainActivity.java new file mode 100644 index 0000000..c7cd539 --- /dev/null +++ b/app/src/main/java/ru/ppzh/filemanager/MainActivity.java @@ -0,0 +1,346 @@ +package ru.ppzh.filemanager; + +import android.app.AlertDialog; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.net.Uri; +import android.os.Bundle; +import android.os.Environment; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.MenuItem; +import android.view.View; +import android.webkit.MimeTypeMap; +import android.widget.EditText; +import android.widget.Toast; + +import java.io.File; +import java.text.DateFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.List; + +public class MainActivity extends AppCompatActivity { + public static final String TAG = "MainActivity"; + public static final String IMAGE_PATH = "ru.ppzh.image_path"; + public static final String CURRENT_FOLDER_PATH = "ru.ppzh.current_folder_path"; + public static final int FILE_IMAGE_PREVIEW_DIMENSION = 50; + + private RecyclerView mRecyclerView; + private RecyclerAdapter mAdapter; + private RecyclerView.LayoutManager mLayoutManager; + private File currentFolder; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main_activity); + mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view); + mRecyclerView.setHasFixedSize(true); + mLayoutManager = new LinearLayoutManager(this); + mRecyclerView.setLayoutManager(mLayoutManager); + + //Log.i(TAG, Environment.getExternalStorageState()); + + // For now it works only with embedded external storage + // TODO add ability to explore sd card filesystem + + if (isExternalStorageAccessable()) { + if (savedInstanceState != null) { + String path = savedInstanceState.getString(CURRENT_FOLDER_PATH); + + //Log.i(TAG, "Restore currentFolder, path: " + path); + + currentFolder = new File(path); + } else { + currentFolder = Environment.getExternalStorageDirectory(); + } + } else { + currentFolder = new File("", getString(R.string.no_storage)); + } + + mAdapter = new RecyclerAdapter(getFiles(currentFolder), this); + mRecyclerView.setAdapter(mAdapter); + + mRecyclerView.addOnItemTouchListener( + new RecyclerItemClickListener(this, + new RecyclerItemClickListener.OnItemClickListener() { + @Override + public void onItemClick(View view, int position) { + Item item = mAdapter.getItem(position); + + if (item.isDirectory()) { + currentFolder = new File(item.getPath()); + mAdapter.setData(getFiles(currentFolder)); + mAdapter.notifyDataSetChanged(); + } else { + open(item); + } + } + } + ) + ); + + registerForContextMenu(mRecyclerView); + } + + private void open(Item item) { + if (isImage(new File(item.getPath()))) { + openWithOwnViewer(item); + } else { + openWithExternalApp(item); + } + } + + private void openWithOwnViewer(Item item) { + Intent intent = new Intent(this, ImageViewer.class); + intent.putExtra(IMAGE_PATH, item.getPath()); + startActivity(intent); + } + + private void openWithExternalApp(Item item) { + if (!openFile(item)) { + Toast.makeText( + getApplicationContext(), + R.string.unknown_file, + Toast.LENGTH_LONG + ).show(); + } + } + + public boolean isExternalStorageAccessable() { + String state = Environment.getExternalStorageState(); + return Environment.MEDIA_MOUNTED.equals(state); + } + + boolean openFile(Item item) { + final Intent intent = new Intent(Intent.ACTION_VIEW); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.setData(Uri.fromFile( + new File(item.getPath()) + )); + + final ResolveInfo defaultResolution = + getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY); + if (defaultResolution != null) { + final ActivityInfo activity = defaultResolution.activityInfo; + + //Log.i(TAG, "default - " + activity.name); + + if (!activity.name.equals("com.android.internal.app.ResolverActivity")) { + intent.setClassName(activity.applicationInfo.packageName, activity.name); + startActivity(intent); + return true; + } + } + + final List resolveInfoList = + getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); + if (!resolveInfoList.isEmpty()) { + + //Log.i(TAG, "from list - " + resolveInfoList.get(0).activityInfo.name); + + intent.setClassName(resolveInfoList.get(0).activityInfo.packageName, + resolveInfoList.get(0).activityInfo.name); + startActivity(intent); + return true; + } + return false; + } + + private List getFiles(File file) { + File[] files = file.listFiles(); + List dirs = new ArrayList(); + List fls = new ArrayList(); + + this.setTitle(file.getName()); + + String filename, modificationDate, path; + Bitmap preview; + ImageLoader imageLoader = new ImageLoader(); + for (File f : files) { + filename = f.getName(); + modificationDate = DateFormat.getDateTimeInstance().format( + new Date(f.lastModified()) + ); + path = f.getAbsolutePath(); + + preview = null; + if (f.isDirectory()) { + preview = BitmapFactory.decodeResource(getResources(), + R.drawable.ic_folder_black_48dp); + dirs.add( + new Item(filename, modificationDate, path, preview, true) + ); + } else { + if (isImage(f)) { + preview = imageLoader.decodeSampledBitmapFromFile( + path, + FILE_IMAGE_PREVIEW_DIMENSION, + FILE_IMAGE_PREVIEW_DIMENSION + ); + } + + if (preview == null) { + preview = BitmapFactory.decodeResource(getResources(), + R.drawable.ic_file_black_48dp); + } + + fls.add( + new Item(filename, modificationDate, path, preview, false) + ); + } + } + Collections.sort(dirs); + Collections.sort(fls); + dirs.addAll(fls); + + if (!(file.getAbsolutePath() + .equals(Environment.getExternalStorageDirectory() + .getAbsolutePath()))) { + dirs.add(0, + new Item("..", "", + file.getParentFile().getAbsolutePath(), + BitmapFactory.decodeResource(getResources(), + R.drawable.ic_folder_parent_black_48dp), + true) + ); + } + + return dirs; + } + + private boolean isImage(File f) { + String mime = null; + String extension = MimeTypeMap.getFileExtensionFromUrl(f.toURI().toString()); + if (extension != null) { + mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension); + } + + //Log.i(TAG, f.getName() + " " + mime); + + return mime != null && mime.split("/")[0].equals("image"); + } + + @Override + public boolean onContextItemSelected(MenuItem menuItem) { + int position = mAdapter.getPosition(); + Item item = mAdapter.getItem(position); + switch (menuItem.getItemId()) { + case R.id.open: + open(item); + return true; + case R.id.rename: + openRenameDialog(item); + return true; + case R.id.delete: + openDeleteDialog(item); + return true; + } + return super.onContextItemSelected(menuItem); + } + + private void openRenameDialog(final Item item) { + final EditText renamePrompt = new EditText(this); + String filename = item.getName(); + String extension = item.getExtension(); + renamePrompt.setText(filename.substring(0, filename.lastIndexOf(extension))); + + new AlertDialog.Builder(this) + .setTitle(R.string.rename) + .setMessage(R.string.rename_msg) + .setView(renamePrompt) + .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + String newFilename = renamePrompt.getText().toString(); + if (isCorrectFilename(newFilename)) { + String newAbsolutePath = constructNewAbsolutePath(item, newFilename); + File newFile = new File(newAbsolutePath); + renameFile(item, newFile); + } else { + Toast.makeText( + getApplicationContext(), + R.string.rename_error_msg, + Toast.LENGTH_LONG + ).show(); + } + } + }) + .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + // nothing to do here + } + }) + .create() + .show(); + } + + private boolean isCorrectFilename(String newFilename) { + // TODO + // Check if filename is correct, + // i.e. doesn't match others filenames + // or consist of forbidden characters. + + // Haven't had enough time to do this. + return true; + } + + private String constructNewAbsolutePath(Item item, String newFilename) { + String path = item.getPath(); + return path.substring(0, path.lastIndexOf('/') + 1) + newFilename + item.getExtension(); + } + + private void renameFile(Item item, File newFile) { + File file = new File(item.getPath()); + if (file.renameTo(newFile) && mAdapter.renameItem(item, newFile)) { + mAdapter.notifyDataSetChanged(); + } else { + Toast.makeText(this, R.string.rename_error_msg, Toast.LENGTH_LONG).show(); + } + } + + private void openDeleteDialog(final Item item) { + new AlertDialog.Builder(this) + .setTitle(R.string.delete) + .setMessage(R.string.delete_msg) + .setCancelable(true) + .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + deleteFileFromDevice(item); + } + }) + .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + // nothing to do here + } + }) + .create() + .show(); + } + + private void deleteFileFromDevice(Item item) { + File file = new File(item.getPath()); + if (file.delete() && mAdapter.deleteItem(item)) { + mAdapter.notifyDataSetChanged(); + } else { + Toast.makeText(this, R.string.delete_error_msg, Toast.LENGTH_LONG).show(); + } + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + outState.putString(CURRENT_FOLDER_PATH, currentFolder.getAbsolutePath()); + super.onSaveInstanceState(outState); + } +} diff --git a/app/src/main/java/ru/ppzh/filemanager/RecyclerAdapter.java b/app/src/main/java/ru/ppzh/filemanager/RecyclerAdapter.java new file mode 100644 index 0000000..156fec6 --- /dev/null +++ b/app/src/main/java/ru/ppzh/filemanager/RecyclerAdapter.java @@ -0,0 +1,120 @@ +package ru.ppzh.filemanager; + +import android.content.Context; +import android.support.v7.widget.RecyclerView; +import android.view.ContextMenu; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import java.io.File; +import java.text.DateFormat; +import java.util.Date; +import java.util.List; + +public class RecyclerAdapter extends RecyclerView.Adapter + implements View.OnCreateContextMenuListener { + private Context context; + private List files; + private int position; + + public RecyclerAdapter(List files, Context context) { + this.files = files; + this.context = context; + } + + public int getPosition() { + return position; + } + + public void setPosition(int position) { + this.position = position; + } + + @Override + public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View v = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.item_layout, parent, false); + return new ViewHolder(v); + } + + @Override + public void onBindViewHolder(final ViewHolder holder, int position) { + holder.image.setImageBitmap(files.get(position).getPreview()); + holder.filename.setText(files.get(position).getName()); + holder.modified.setText(files.get(position).getDate()); + holder.itemView.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + setPosition(holder.getAdapterPosition()); + return false; + } + }); + + } + + @Override + public void onViewRecycled(ViewHolder holder) { + holder.itemView.setOnLongClickListener(null); + super.onViewRecycled(holder); + } + + @Override + public int getItemCount() { + return files.size(); + } + + public Item getItem(int position) { + return files.get(position); + } + + public void setData(List files) { + this.files = files; + } + + public boolean deleteItem(Item item) { + return files.remove(item); + } + + public boolean renameItem(Item item, File newFile) { + if (deleteItem(item)) { + item.setPath(newFile.getAbsolutePath()); + item.setName(newFile.getName()); + item.setDate( + DateFormat.getDateTimeInstance().format( + new Date(newFile.lastModified()) + ) + ); + files.add(item); + return true; + } + return false; + } + + public class ViewHolder extends RecyclerView.ViewHolder { + public ImageView image; + public TextView filename; + public TextView modified; + + public ViewHolder(View v) { + super(v); + v.setOnCreateContextMenuListener(RecyclerAdapter.this); + image = (ImageView) v.findViewById(R.id.file_img); + filename = (TextView) v.findViewById(R.id.file_name); + modified = (TextView) v.findViewById(R.id.last_modified); + } + } + + @Override + public void onCreateContextMenu(ContextMenu menu, View v, + ContextMenu.ContextMenuInfo menuInfo) { + if (!files.get(position).isDirectory()) { + menu.add(Menu.NONE, R.id.open, Menu.NONE, R.string.open); + menu.add(Menu.NONE, R.id.rename, Menu.NONE, R.string.rename); + menu.add(Menu.NONE, R.id.delete, Menu.NONE, R.string.delete); + } + } +} diff --git a/app/src/main/java/ru/ppzh/filemanager/RecyclerItemClickListener.java b/app/src/main/java/ru/ppzh/filemanager/RecyclerItemClickListener.java new file mode 100644 index 0000000..70e704e --- /dev/null +++ b/app/src/main/java/ru/ppzh/filemanager/RecyclerItemClickListener.java @@ -0,0 +1,45 @@ +package ru.ppzh.filemanager; + +import android.content.Context; +import android.support.v7.widget.RecyclerView; +import android.view.GestureDetector; +import android.view.MotionEvent; +import android.view.View; + +public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListener { + private OnItemClickListener mListener; + + public interface OnItemClickListener { + public void onItemClick(View view, int position); + } + + GestureDetector mGestureDetector; + + public RecyclerItemClickListener(Context context, OnItemClickListener listener) { + mListener = listener; + mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { + @Override + public boolean onSingleTapUp(MotionEvent e) { + return true; + } + }); + } + + @Override + public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) { + View childView = view.findChildViewUnder(e.getX(), e.getY()); + if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) { + mListener.onItemClick(childView, view.getChildPosition(childView)); + return true; + } + return false; + } + + @Override + public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) { + } + + @Override + public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-hdpi/ic_folder_black_48dp.png b/app/src/main/res/drawable-hdpi/ic_folder_black_48dp.png new file mode 100644 index 0000000..5c4360a Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_folder_black_48dp.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_folder_black_48dp.png b/app/src/main/res/drawable-mdpi/ic_folder_black_48dp.png new file mode 100644 index 0000000..49272b0 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_folder_black_48dp.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_folder_black_48dp.png b/app/src/main/res/drawable-xhdpi/ic_folder_black_48dp.png new file mode 100644 index 0000000..073d853 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_folder_black_48dp.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_folder_black_48dp.png b/app/src/main/res/drawable-xxhdpi/ic_folder_black_48dp.png new file mode 100644 index 0000000..c7a13b4 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_folder_black_48dp.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_folder_black_48dp.png b/app/src/main/res/drawable-xxxhdpi/ic_folder_black_48dp.png new file mode 100644 index 0000000..27e524f Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_folder_black_48dp.png differ diff --git a/app/src/main/res/drawable/ic_file_black_48dp.png b/app/src/main/res/drawable/ic_file_black_48dp.png new file mode 100644 index 0000000..84eba39 Binary files /dev/null and b/app/src/main/res/drawable/ic_file_black_48dp.png differ diff --git a/app/src/main/res/drawable/ic_folder_parent_black_48dp.png b/app/src/main/res/drawable/ic_folder_parent_black_48dp.png new file mode 100644 index 0000000..ad31faf Binary files /dev/null and b/app/src/main/res/drawable/ic_folder_parent_black_48dp.png differ diff --git a/app/src/main/res/layout/image_viewer.xml b/app/src/main/res/layout/image_viewer.xml new file mode 100644 index 0000000..5e033d3 --- /dev/null +++ b/app/src/main/res/layout/image_viewer.xml @@ -0,0 +1,9 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_layout.xml b/app/src/main/res/layout/item_layout.xml new file mode 100644 index 0000000..081eab4 --- /dev/null +++ b/app/src/main/res/layout/item_layout.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/main_activity.xml b/app/src/main/res/layout/main_activity.xml new file mode 100644 index 0000000..13c6f18 --- /dev/null +++ b/app/src/main/res/layout/main_activity.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/layout/rename_prompt.xml b/app/src/main/res/layout/rename_prompt.xml new file mode 100644 index 0000000..c777ede --- /dev/null +++ b/app/src/main/res/layout/rename_prompt.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/context_menu.xml b/app/src/main/res/menu/context_menu.xml new file mode 100644 index 0000000..5fb2246 --- /dev/null +++ b/app/src/main/res/menu/context_menu.xml @@ -0,0 +1,10 @@ + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e2827ac..f81f972 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,3 +1,14 @@ - lesson5 + File manager + No storage found + File image + No application for this type of files. + + Open + Delete + Rename + Are you sure you want to delete this file? + Can\'t delete this file. + Enter new name + Can\'t rename this file.