Skip to content

Commit b12f0ca

Browse files
Implemented import - First version
1 parent 76f9603 commit b12f0ca

File tree

6 files changed

+243
-14
lines changed

6 files changed

+243
-14
lines changed

app/src/main/AndroidManifest.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
xmlns:tools="http://schemas.android.com/tools"
44
package="com.butramyou.listoffilms">
55

6-
<!-- <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />-->
76
<uses-permission android:name="android.permission.VIBRATE" />
7+
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
88
<application
9+
android:requestLegacyExternalStorage="true"
910
android:allowBackup="true"
1011
android:dataExtractionRules="@xml/data_extraction_rules"
1112
android:fullBackupContent="@xml/backup_rules"
@@ -20,7 +21,6 @@
2021
android:exported="true">
2122
<intent-filter>
2223
<action android:name="android.intent.action.MAIN" />
23-
2424
<category android:name="android.intent.category.LAUNCHER" />
2525
</intent-filter>
2626
</activity>

app/src/main/java/com/butramyou/listoffilms/MainActivity.java

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
package com.butramyou.listoffilms;
22

3+
import android.Manifest;
34
import android.annotation.SuppressLint;
5+
import android.app.Activity;
6+
import android.content.Intent;
7+
import android.content.pm.PackageManager;
8+
import android.net.Uri;
49
import android.os.Bundle;
510
import android.view.Menu;
611
import android.view.MenuItem;
712

13+
import androidx.activity.result.ActivityResultLauncher;
14+
import androidx.activity.result.contract.ActivityResultContracts;
815
import androidx.appcompat.app.AppCompatActivity;
16+
import androidx.core.app.ActivityCompat;
917
import androidx.fragment.app.Fragment;
1018
import androidx.fragment.app.FragmentTransaction;
1119

@@ -16,17 +24,31 @@
1624
import com.butramyou.listoffilms.fragments.ViewedFilmsFragment;
1725
import com.butramyou.listoffilms.helpers.BottomNavigationViewHelper;
1826
import com.butramyou.listoffilms.service.ExportService;
27+
import com.butramyou.listoffilms.service.ImportService;
1928
import com.google.android.material.bottomnavigation.BottomNavigationView;
2029
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
2130

2231
public class MainActivity extends AppCompatActivity {
2332

33+
private ActivityResultLauncher<Intent> someActivityResultLauncher;
34+
2435
@SuppressLint("NonConstantResourceId")
2536
@Override
2637
protected void onCreate(Bundle savedInstanceState) {
2738
super.onCreate(savedInstanceState);
2839

29-
com.butramyou.listoffilms.databinding.ActivityMainBinding binding = ActivityMainBinding.inflate(getLayoutInflater());
40+
someActivityResultLauncher = registerForActivityResult(
41+
new ActivityResultContracts.StartActivityForResult(),
42+
result -> {
43+
if (result.getResultCode() == Activity.RESULT_OK) {
44+
Intent data = result.getData();
45+
Uri uri = data.getData();
46+
ImportService importService = new ImportService(this);
47+
importService.importFile(uri);
48+
}
49+
});
50+
51+
ActivityMainBinding binding = ActivityMainBinding.inflate(getLayoutInflater());
3052
setContentView(binding.getRoot());
3153

3254
BottomNavigationView bottomNavigationView = findViewById(R.id.bottom_navigation);
@@ -78,6 +100,11 @@ public boolean onCreateOptionsMenu(Menu menu) {
78100
public boolean onOptionsItemSelected(MenuItem item) {
79101
int id = item.getItemId();
80102

103+
if (id == R.id.action_import) {
104+
askPermissionAndBrowseFile();
105+
openSomeActivityForResult();
106+
}
107+
81108
if (id == R.id.action_export) {
82109
new MaterialAlertDialogBuilder(this)
83110
.setMessage(this.getString(R.string.is_export_file))
@@ -100,4 +127,24 @@ public boolean onOptionsItemSelected(MenuItem item) {
100127

101128
return super.onOptionsItemSelected(item);
102129
}
130+
131+
private void askPermissionAndBrowseFile() {
132+
int MY_REQUEST_CODE_PERMISSION = 1000;
133+
int permission = ActivityCompat.checkSelfPermission(this,
134+
Manifest.permission.READ_EXTERNAL_STORAGE);
135+
136+
if (permission != PackageManager.PERMISSION_GRANTED) {
137+
this.requestPermissions(
138+
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
139+
MY_REQUEST_CODE_PERMISSION
140+
);
141+
}
142+
}
143+
144+
private void openSomeActivityForResult() {
145+
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
146+
intent.setType("application/json");
147+
intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
148+
someActivityResultLauncher.launch(intent);
149+
}
103150
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package com.butramyou.listoffilms.service;
2+
3+
import android.content.Context;
4+
import android.net.Uri;
5+
6+
import com.butramyou.listoffilms.helpers.DatabaseHelper;
7+
import com.butramyou.listoffilms.model.Film;
8+
import com.butramyou.listoffilms.utils.FileUtils;
9+
import com.google.gson.Gson;
10+
import com.google.gson.GsonBuilder;
11+
import com.google.gson.reflect.TypeToken;
12+
13+
import java.io.BufferedReader;
14+
import java.io.File;
15+
import java.io.FileInputStream;
16+
import java.io.IOException;
17+
import java.io.InputStreamReader;
18+
import java.lang.reflect.Type;
19+
import java.util.ArrayList;
20+
import java.util.List;
21+
22+
public class ImportService {
23+
24+
private final Context context;
25+
private final Gson gson = new GsonBuilder().serializeNulls().setPrettyPrinting().create();
26+
27+
public ImportService(Context context) {
28+
this.context = context;
29+
}
30+
31+
public void importFile(Uri uri) {
32+
try {
33+
String test = FileUtils.copyFileToInternalStorage(context, uri, "import");
34+
File importFile = new File(test);
35+
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(importFile)));
36+
37+
StringBuilder importJson = new StringBuilder();
38+
39+
String line;
40+
while ((line = reader.readLine()) != null) {
41+
importJson.append(line);
42+
}
43+
DatabaseHelper databaseHelper = new DatabaseHelper(context);
44+
45+
List<Film> films = convertToFilm(importJson.toString());
46+
films.forEach(film -> {
47+
Film newFilm = new Film(film.getName(), film.isViewed(), film.isDownloaded());
48+
databaseHelper.addFilm(newFilm);
49+
});
50+
51+
} catch (IOException e) {
52+
e.printStackTrace();
53+
}
54+
}
55+
56+
private List<Film> convertToFilm(String importJson) {
57+
Type listOfFilmsObject = new TypeToken<ArrayList<Film>>() {}.getType();
58+
return gson.fromJson(importJson, listOfFilmsObject);
59+
}
60+
}
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
package com.butramyou.listoffilms.utils;
2+
3+
import android.annotation.SuppressLint;
4+
import android.content.Context;
5+
import android.database.Cursor;
6+
import android.net.Uri;
7+
import android.os.Environment;
8+
import android.provider.DocumentsContract;
9+
import android.provider.OpenableColumns;
10+
import android.util.Log;
11+
12+
import com.butramyou.listoffilms.exceptions.ListOfFilmsException;
13+
14+
import java.io.File;
15+
import java.io.FileOutputStream;
16+
import java.io.InputStream;
17+
18+
public class FileUtils {
19+
20+
/**
21+
* Get a file path from a Uri.
22+
* <br>
23+
* Callers should check whether the path is local before assuming it
24+
* represents a local file.
25+
*
26+
* @param uri The Uri to query.
27+
*/
28+
@SuppressLint("NewApi")
29+
public static String getPath(final Uri uri) {
30+
final String docId = DocumentsContract.getDocumentId(uri);
31+
final String[] split = docId.split(":");
32+
33+
String fullPath = getPathFromExtSD(split);
34+
if (!fullPath.equals("")) {
35+
return fullPath;
36+
} else {
37+
return null;
38+
}
39+
}
40+
41+
/**
42+
* Check if a file exists on device
43+
*
44+
* @param filePath The absolute file path
45+
*/
46+
private static boolean fileExists(String filePath) {
47+
File file = new File(filePath);
48+
return file.exists();
49+
}
50+
51+
/**
52+
* Get full file path from external storage
53+
*
54+
* @param pathData The storage type and the relative path
55+
*/
56+
private static String getPathFromExtSD(String[] pathData) {
57+
final String type = pathData[0];
58+
final String relativePath = "/" + pathData[1];
59+
String fullPath;
60+
61+
if ("primary".equalsIgnoreCase(type)) {
62+
fullPath = Environment.getExternalStorageDirectory() + relativePath;
63+
if (fileExists(fullPath)) {
64+
return fullPath;
65+
}
66+
}
67+
68+
fullPath = System.getenv("SECONDARY_STORAGE") + relativePath;
69+
if (fileExists(fullPath)) {
70+
return fullPath;
71+
}
72+
73+
fullPath = System.getenv("EXTERNAL_STORAGE") + relativePath;
74+
if (fileExists(fullPath)) {
75+
return fullPath;
76+
}
77+
throw new ListOfFilmsException("No file found on the path");
78+
}
79+
80+
@SuppressLint("Recycle")
81+
public static String copyFileToInternalStorage(Context context, Uri uri, String newDirName) {
82+
Cursor returnCursor = context.getContentResolver().query(uri, new String[]{
83+
OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE
84+
}, null, null, null);
85+
int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
86+
returnCursor.moveToFirst();
87+
String name = (returnCursor.getString(nameIndex));
88+
89+
File output;
90+
if (!newDirName.equals("")) {
91+
File dir = new File(context.getFilesDir() + "/" + newDirName);
92+
if (!dir.exists()) {
93+
dir.mkdir();
94+
}
95+
output = new File(context.getFilesDir() + "/" + newDirName + "/" + name);
96+
} else {
97+
output = new File(context.getFilesDir() + "/" + name);
98+
}
99+
try {
100+
InputStream inputStream = context.getContentResolver().openInputStream(uri);
101+
FileOutputStream outputStream = new FileOutputStream(output);
102+
int read = 0;
103+
int bufferSize = 1024;
104+
final byte[] buffers = new byte[bufferSize];
105+
while ((read = inputStream.read(buffers)) != -1) {
106+
outputStream.write(buffers, 0, read);
107+
}
108+
inputStream.close();
109+
outputStream.close();
110+
} catch (Exception e) {
111+
Log.e("Exception", e.getMessage());
112+
}
113+
114+
return output.getPath();
115+
}
116+
}

app/src/main/res/menu/menu_main.xml

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,22 @@
88
android:title="@string/action_import"
99
app:showAsAction="never" />
1010
<item
11-
android:id="@+id/menu_export"
11+
android:id="@+id/action_export"
1212
android:orderInCategory="100"
13-
android:title="@string/action_export_menu"
14-
app:showAsAction="never">
15-
<menu>
16-
<item android:id="@+id/create_new"
17-
android:title="@string/action_share_export" />
18-
<item android:id="@+id/action_export"
19-
android:title="@string/action_export" />
20-
</menu>
21-
</item>
13+
android:title="@string/action_export"
14+
app:showAsAction="never" />
15+
<!-- <item-->
16+
<!-- android:id="@+id/menu_export"-->
17+
<!-- android:orderInCategory="100"-->
18+
<!-- android:title="@string/action_export_menu"-->
19+
<!-- app:showAsAction="never">-->
20+
<!-- <menu>-->
21+
<!-- <item android:id="@+id/create_new"-->
22+
<!-- android:title="@string/action_share_export" />-->
23+
<!-- <item android:id="@+id/action_export"-->
24+
<!-- android:title="@string/action_export" />-->
25+
<!-- </menu>-->
26+
<!-- </item>-->
2227
<item
2328
android:id="@+id/action_about_author"
2429
android:orderInCategory="100"

app/src/main/res/values/strings.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
<string name="app_name">List of films</string>
33
<string name="action_about_author">About author</string>
44
<string name="action_import">Import</string>
5-
<string name="action_export">Create export file</string>
5+
<!-- <string name="action_export">Create export file</string>-->
6+
<string name="action_export">Export</string>
67
<string name="action_share_export">Share an export</string>
78
<string name="action_export_menu">Export Menu</string>
89
<string name="viewed_films_label">Viewed</string>

0 commit comments

Comments
 (0)