mirror of
https://github.com/CatimaLoyalty/Android.git
synced 2026-02-02 11:12:23 -05:00
Import and export .csv and images as .zip
This commit is contained in:
@@ -78,8 +78,8 @@ public class ImportExportActivity extends AppCompatActivity
|
||||
// Check that there is a file manager available
|
||||
final Intent intentCreateDocumentAction = new Intent(Intent.ACTION_CREATE_DOCUMENT);
|
||||
intentCreateDocumentAction.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
intentCreateDocumentAction.setType("text/csv");
|
||||
intentCreateDocumentAction.putExtra(Intent.EXTRA_TITLE, "Catima.csv");
|
||||
intentCreateDocumentAction.setType("application/zip");
|
||||
intentCreateDocumentAction.putExtra(Intent.EXTRA_TITLE, "Catima.zip");
|
||||
|
||||
Button exportButton = findViewById(R.id.exportButton);
|
||||
exportButton.setOnClickListener(new View.OnClickListener()
|
||||
|
||||
@@ -77,7 +77,7 @@ class ImportExportTask extends AsyncTask<Void, Void, ImportExportResult>
|
||||
try
|
||||
{
|
||||
OutputStreamWriter writer = new OutputStreamWriter(stream, Charset.forName("UTF-8"));
|
||||
result = MultiFormatExporter.exportData(context, db, writer, format);
|
||||
result = MultiFormatExporter.exportData(context, db, stream, format);
|
||||
writer.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
|
||||
@@ -33,6 +33,7 @@ import java.util.Currency;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
|
||||
@@ -234,30 +235,6 @@ public class Utils {
|
||||
return bos.toByteArray();
|
||||
}
|
||||
|
||||
static public Bitmap byteArrayToBitmap(byte[] byteArray) {
|
||||
if (byteArray == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);
|
||||
}
|
||||
|
||||
static public String bitmapToBase64(Bitmap bitmap) {
|
||||
if (bitmap == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Base64.encodeToString(bitmapToByteArray(bitmap), Base64.URL_SAFE);
|
||||
}
|
||||
|
||||
static public Bitmap base64ToBitmap(String base64) {
|
||||
if (base64 == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return byteArrayToBitmap(Base64.decode(base64, Base64.URL_SAFE));
|
||||
}
|
||||
|
||||
static public Bitmap resizeBitmap(Bitmap bitmap) {
|
||||
if (bitmap == null) {
|
||||
return null;
|
||||
@@ -307,7 +284,7 @@ public class Utils {
|
||||
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
|
||||
}
|
||||
|
||||
static private String getCardImageFileName(int loyaltyCardId, boolean front) {
|
||||
static public String getCardImageFileName(int loyaltyCardId, boolean front) {
|
||||
StringBuilder cardImageFileNameBuilder = new StringBuilder();
|
||||
|
||||
cardImageFileNameBuilder.append("card_");
|
||||
@@ -323,23 +300,26 @@ public class Utils {
|
||||
return cardImageFileNameBuilder.toString();
|
||||
}
|
||||
|
||||
static public void saveCardImage(Context context, Bitmap bitmap, int loyaltyCardId, boolean front) throws FileNotFoundException {
|
||||
String fileName = getCardImageFileName(loyaltyCardId, front);
|
||||
|
||||
static public void saveCardImage(Context context, Bitmap bitmap, String fileName) throws FileNotFoundException {
|
||||
if (bitmap == null) {
|
||||
context.deleteFile(fileName);
|
||||
return;
|
||||
}
|
||||
|
||||
FileOutputStream out = context.openFileOutput(getCardImageFileName(loyaltyCardId, front), Context.MODE_PRIVATE);
|
||||
FileOutputStream out = context.openFileOutput(fileName, Context.MODE_PRIVATE);
|
||||
|
||||
bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
|
||||
|
||||
}
|
||||
|
||||
static public Bitmap retrieveCardImage(Context context, int loyaltyCardId, boolean front) {
|
||||
static public void saveCardImage(Context context, Bitmap bitmap, int loyaltyCardId, boolean front) throws FileNotFoundException {
|
||||
saveCardImage(context, bitmap, getCardImageFileName(loyaltyCardId, front));
|
||||
}
|
||||
|
||||
static public Bitmap retrieveCardImage(Context context, String fileName) {
|
||||
FileInputStream in;
|
||||
try {
|
||||
in = context.openFileInput(getCardImageFileName(loyaltyCardId, front));
|
||||
in = context.openFileInput(fileName);
|
||||
} catch (FileNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
@@ -347,6 +327,10 @@ public class Utils {
|
||||
return BitmapFactory.decodeStream(in);
|
||||
}
|
||||
|
||||
static public Bitmap retrieveCardImage(Context context, int loyaltyCardId, boolean front) {
|
||||
return retrieveCardImage(context, getCardImageFileName(loyaltyCardId, front));
|
||||
}
|
||||
|
||||
static public Object hashmapGetOrDefault(HashMap hashMap, String key, Object defaultValue) {
|
||||
Object value = hashMap.get(key);
|
||||
if (value == null) {
|
||||
|
||||
36
app/src/main/java/protect/card_locker/ZipUtils.java
Normal file
36
app/src/main/java/protect/card_locker/ZipUtils.java
Normal file
@@ -0,0 +1,36 @@
|
||||
package protect.card_locker;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
|
||||
import net.lingala.zip4j.io.inputstream.ZipInputStream;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class ZipUtils {
|
||||
static public String read(ZipInputStream zipInputStream) throws IOException {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
Reader reader = new BufferedReader(new InputStreamReader(zipInputStream, Charset.forName(StandardCharsets.UTF_8.name())));
|
||||
int c;
|
||||
while ((c = reader.read()) != -1) {
|
||||
stringBuilder.append((char) c);
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
static public Bitmap readImage(ZipInputStream zipInputStream) {
|
||||
return BitmapFactory.decodeStream(zipInputStream);
|
||||
}
|
||||
|
||||
static public JSONObject readJSON(ZipInputStream zipInputStream) throws IOException, JSONException {
|
||||
return new JSONObject(read(zipInputStream));
|
||||
}
|
||||
}
|
||||
@@ -1,38 +1,10 @@
|
||||
package protect.card_locker.importexport;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
|
||||
import org.apache.commons.csv.CSVRecord;
|
||||
|
||||
import protect.card_locker.FormatException;
|
||||
import protect.card_locker.Utils;
|
||||
|
||||
public class CSVHelpers {
|
||||
static String IMAGE_FRONT = "frontimage";
|
||||
static String IMAGE_BACK = "backimage";
|
||||
|
||||
/**
|
||||
* Extract an image from the items array. The index into the array
|
||||
* is determined by looking up the index in the fields map using the
|
||||
* "key" as the key. If no such key exists, defaultValue is returned
|
||||
* if it is not null. Otherwise, a FormatException is thrown.
|
||||
*/
|
||||
static Bitmap extractImage(String key, CSVRecord record)
|
||||
{
|
||||
if(record.isMapped(key))
|
||||
{
|
||||
String value = record.get(key);
|
||||
|
||||
if (value.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Utils.base64ToBitmap(value);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract a string from the items array. The index into the array
|
||||
* is determined by looking up the index in the fields map using the
|
||||
|
||||
@@ -2,12 +2,25 @@ package protect.card_locker.importexport;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
|
||||
import net.lingala.zip4j.ZipFile;
|
||||
import net.lingala.zip4j.io.outputstream.ZipOutputStream;
|
||||
import net.lingala.zip4j.model.ZipParameters;
|
||||
import net.lingala.zip4j.util.InternalZipConstants;
|
||||
|
||||
import org.apache.commons.csv.CSVFormat;
|
||||
import org.apache.commons.csv.CSVPrinter;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.util.zip.ZipEntry;
|
||||
|
||||
import protect.card_locker.DBHelper;
|
||||
import protect.card_locker.Group;
|
||||
@@ -18,10 +31,65 @@ import protect.card_locker.Utils;
|
||||
* Class for exporting the database into CSV (Comma Separate Values)
|
||||
* format.
|
||||
*/
|
||||
public class CsvExporter implements Exporter
|
||||
public class CatimaExporter implements Exporter
|
||||
{
|
||||
public void exportData(Context context, DBHelper db, OutputStreamWriter output) throws IOException, InterruptedException
|
||||
public void exportData(Context context, DBHelper db, OutputStream output) throws IOException, InterruptedException
|
||||
{
|
||||
// Necessary vars
|
||||
int readLen;
|
||||
byte[] readBuffer = new byte[InternalZipConstants.BUFF_SIZE];
|
||||
|
||||
// Create zip output stream
|
||||
ZipOutputStream zipOutputStream = new ZipOutputStream(output);
|
||||
|
||||
// Generate CSV
|
||||
ByteArrayOutputStream catimaOutputStream = new ByteArrayOutputStream();
|
||||
OutputStreamWriter catimaOutputStreamWriter = new OutputStreamWriter(catimaOutputStream);
|
||||
writeCSV(db, catimaOutputStreamWriter);
|
||||
|
||||
// Add CSV to zip file
|
||||
ZipParameters csvZipParameters = new ZipParameters();
|
||||
csvZipParameters.setFileNameInZip("catima.csv");
|
||||
zipOutputStream.putNextEntry(csvZipParameters);
|
||||
InputStream csvInputStream = new ByteArrayInputStream(catimaOutputStream.toByteArray());
|
||||
while ((readLen = csvInputStream.read(readBuffer)) != -1) {
|
||||
zipOutputStream.write(readBuffer, 0, readLen);
|
||||
}
|
||||
zipOutputStream.closeEntry();
|
||||
|
||||
// Loop over all cards again
|
||||
Cursor cardCursor = db.getLoyaltyCardCursor();
|
||||
while(cardCursor.moveToNext())
|
||||
{
|
||||
// For each card
|
||||
LoyaltyCard card = LoyaltyCard.toLoyaltyCard(cardCursor);
|
||||
|
||||
// Prepare looping over both front and back image
|
||||
boolean[] frontValues = new boolean[2];
|
||||
frontValues[0] = true;
|
||||
frontValues[1] = false;
|
||||
|
||||
// For each image
|
||||
for (boolean front : frontValues) {
|
||||
// If it exists, add to the .zip file
|
||||
Bitmap image = Utils.retrieveCardImage(context, card.id, front);
|
||||
if (image != null) {
|
||||
ZipParameters imageZipParameters = new ZipParameters();
|
||||
imageZipParameters.setFileNameInZip(Utils.getCardImageFileName(card.id, front));
|
||||
zipOutputStream.putNextEntry(imageZipParameters);
|
||||
InputStream imageInputStream = new ByteArrayInputStream(Utils.bitmapToByteArray(image));
|
||||
while ((readLen = imageInputStream.read(readBuffer)) != -1) {
|
||||
zipOutputStream.write(readBuffer, 0, readLen);
|
||||
}
|
||||
zipOutputStream.closeEntry();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
zipOutputStream.close();
|
||||
}
|
||||
|
||||
private void writeCSV(DBHelper db, OutputStreamWriter output) throws IOException, InterruptedException {
|
||||
CSVPrinter printer = new CSVPrinter(output, CSVFormat.RFC4180);
|
||||
|
||||
// Print the version
|
||||
@@ -62,9 +130,7 @@ public class CsvExporter implements Exporter
|
||||
DBHelper.LoyaltyCardDbIds.BARCODE_ID,
|
||||
DBHelper.LoyaltyCardDbIds.BARCODE_TYPE,
|
||||
DBHelper.LoyaltyCardDbIds.HEADER_COLOR,
|
||||
DBHelper.LoyaltyCardDbIds.STAR_STATUS,
|
||||
CSVHelpers.IMAGE_FRONT,
|
||||
CSVHelpers.IMAGE_BACK);
|
||||
DBHelper.LoyaltyCardDbIds.STAR_STATUS);
|
||||
|
||||
Cursor cardCursor = db.getLoyaltyCardCursor();
|
||||
|
||||
@@ -82,9 +148,7 @@ public class CsvExporter implements Exporter
|
||||
card.barcodeId,
|
||||
card.barcodeType,
|
||||
card.headerColor,
|
||||
card.starStatus,
|
||||
Utils.bitmapToBase64(Utils.retrieveCardImage(context, card.id, true)),
|
||||
Utils.bitmapToBase64(Utils.retrieveCardImage(context, card.id, false)));
|
||||
card.starStatus);
|
||||
|
||||
if(Thread.currentThread().isInterrupted())
|
||||
{
|
||||
@@ -5,11 +5,15 @@ import android.database.sqlite.SQLiteDatabase;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
|
||||
import net.lingala.zip4j.io.inputstream.ZipInputStream;
|
||||
import net.lingala.zip4j.model.LocalFileHeader;
|
||||
|
||||
import org.apache.commons.csv.CSVFormat;
|
||||
import org.apache.commons.csv.CSVParser;
|
||||
import org.apache.commons.csv.CSVRecord;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
@@ -24,6 +28,7 @@ import protect.card_locker.DBHelper;
|
||||
import protect.card_locker.FormatException;
|
||||
import protect.card_locker.Group;
|
||||
import protect.card_locker.Utils;
|
||||
import protect.card_locker.ZipUtils;
|
||||
|
||||
/**
|
||||
* Class for importing a database from CSV (Comma Separate Values)
|
||||
@@ -32,10 +37,33 @@ import protect.card_locker.Utils;
|
||||
* The database's loyalty cards are expected to appear in the CSV data.
|
||||
* A header is expected for the each table showing the names of the columns.
|
||||
*/
|
||||
public class CsvImporter implements Importer
|
||||
public class CatimaImporter implements Importer
|
||||
{
|
||||
public void importData(Context context, DBHelper db, InputStream input, char[] password) throws IOException, FormatException, InterruptedException
|
||||
{
|
||||
public void importData(Context context, DBHelper db, InputStream input, char[] password) throws IOException, FormatException, InterruptedException {
|
||||
// First, check if this is a zip file
|
||||
ZipInputStream zipInputStream = new ZipInputStream(input);
|
||||
LocalFileHeader localFileHeader = zipInputStream.getNextEntry();
|
||||
|
||||
if (localFileHeader == null) {
|
||||
// This is not a zip file, try importing as bare CSV
|
||||
input.reset();
|
||||
importCSV(context, db, input);
|
||||
return;
|
||||
}
|
||||
|
||||
importZipFile(context, db, zipInputStream, localFileHeader);
|
||||
}
|
||||
|
||||
public void importZipFile(Context context, DBHelper db, ZipInputStream input, LocalFileHeader localFileHeader) throws IOException, FormatException, InterruptedException {
|
||||
String fileName = localFileHeader.getFileName();
|
||||
if (fileName.equals("catima.csv")) {
|
||||
importCSV(context, db, new ByteArrayInputStream(ZipUtils.read(input).getBytes()));
|
||||
} else {
|
||||
Utils.saveCardImage(context, ZipUtils.readImage(input), fileName);
|
||||
}
|
||||
}
|
||||
|
||||
public void importCSV(Context context, DBHelper db, InputStream input) throws IOException, FormatException, InterruptedException {
|
||||
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
|
||||
|
||||
bufferedReader.mark(100);
|
||||
@@ -278,9 +306,6 @@ public class CsvImporter implements Importer
|
||||
if (starStatus != 1) starStatus = 0;
|
||||
|
||||
helper.insertLoyaltyCard(database, id, store, note, expiry, balance, balanceType, cardId, barcodeId, barcodeType, headerColor, starStatus);
|
||||
|
||||
Utils.saveCardImage(context, CSVHelpers.extractImage(CSVHelpers.IMAGE_FRONT, record), id, true);
|
||||
Utils.saveCardImage(context, CSVHelpers.extractImage(CSVHelpers.IMAGE_BACK, record), id, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3,6 +3,7 @@ package protect.card_locker.importexport;
|
||||
import android.content.Context;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
|
||||
import protect.card_locker.DBHelper;
|
||||
@@ -17,5 +18,5 @@ public interface Exporter
|
||||
* Export the database to the output stream in a given format.
|
||||
* @throws IOException
|
||||
*/
|
||||
void exportData(Context context, DBHelper db, OutputStreamWriter output) throws IOException, InterruptedException;
|
||||
void exportData(Context context, DBHelper db, OutputStream output) throws IOException, InterruptedException;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
|
||||
import protect.card_locker.DBHelper;
|
||||
@@ -22,14 +23,14 @@ public class MultiFormatExporter
|
||||
* another ImportExportResult otherwise. If not Success, partial data may have been
|
||||
* written to the output stream, and it should be discarded.
|
||||
*/
|
||||
public static ImportExportResult exportData(Context context, DBHelper db, OutputStreamWriter output, DataFormat format)
|
||||
public static ImportExportResult exportData(Context context, DBHelper db, OutputStream output, DataFormat format)
|
||||
{
|
||||
Exporter exporter = null;
|
||||
|
||||
switch(format)
|
||||
{
|
||||
case Catima:
|
||||
exporter = new CsvExporter();
|
||||
exporter = new CatimaExporter();
|
||||
break;
|
||||
default:
|
||||
Log.e(TAG, "Failed to export data, unknown format " + format.name());
|
||||
|
||||
@@ -36,7 +36,7 @@ public class MultiFormatImporter
|
||||
switch(format)
|
||||
{
|
||||
case Catima:
|
||||
importer = new CsvImporter();
|
||||
importer = new CatimaImporter();
|
||||
break;
|
||||
case Fidme:
|
||||
importer = new FidmeImporter();
|
||||
@@ -60,7 +60,7 @@ public class MultiFormatImporter
|
||||
{
|
||||
return ImportExportResult.BadPassword;
|
||||
}
|
||||
catch(IOException | FormatException | InterruptedException | JSONException | ParseException e)
|
||||
catch(IOException | FormatException | InterruptedException | JSONException | ParseException | NullPointerException e)
|
||||
{
|
||||
Log.e(TAG, "Failed to import data", e);
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import java.util.List;
|
||||
import protect.card_locker.DBHelper;
|
||||
import protect.card_locker.FormatException;
|
||||
import protect.card_locker.Utils;
|
||||
import protect.card_locker.ZipUtils;
|
||||
|
||||
/**
|
||||
* Class for importing a database from CSV (Comma Separate Values)
|
||||
@@ -83,7 +84,7 @@ public class StocardImporter implements Importer
|
||||
if (nameParts.length == cardBaseName.length + 1) {
|
||||
// Ignore the .txt file
|
||||
if (fileName.endsWith(".json")) {
|
||||
JSONObject jsonObject = readJSON(zipInputStream);
|
||||
JSONObject jsonObject = ZipUtils.readJSON(zipInputStream);
|
||||
|
||||
loyaltyCardHashMap = appendToLoyaltyCardHashMap(
|
||||
loyaltyCardHashMap,
|
||||
@@ -115,7 +116,7 @@ public class StocardImporter implements Importer
|
||||
loyaltyCardHashMap,
|
||||
cardName,
|
||||
"note",
|
||||
readJSON(zipInputStream)
|
||||
ZipUtils.readJSON(zipInputStream)
|
||||
.getString("content")
|
||||
);
|
||||
} else if (fileName.endsWith("/images/front.png")) {
|
||||
@@ -123,14 +124,14 @@ public class StocardImporter implements Importer
|
||||
loyaltyCardHashMap,
|
||||
cardName,
|
||||
"frontImage",
|
||||
readImage(zipInputStream)
|
||||
ZipUtils.readImage(zipInputStream)
|
||||
);
|
||||
} else if (fileName.endsWith("/images/back.png")) {
|
||||
loyaltyCardHashMap = appendToLoyaltyCardHashMap(
|
||||
loyaltyCardHashMap,
|
||||
cardName,
|
||||
"backImage",
|
||||
readImage(zipInputStream)
|
||||
ZipUtils.readImage(zipInputStream)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -188,24 +189,6 @@ public class StocardImporter implements Importer
|
||||
return true;
|
||||
}
|
||||
|
||||
private String read(ZipInputStream zipInputStream) throws IOException {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
Reader reader = new BufferedReader(new InputStreamReader(zipInputStream, Charset.forName(StandardCharsets.UTF_8.name())));
|
||||
int c;
|
||||
while ((c = reader.read()) != -1) {
|
||||
stringBuilder.append((char) c);
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
private Bitmap readImage(ZipInputStream zipInputStream) {
|
||||
return BitmapFactory.decodeStream(zipInputStream);
|
||||
}
|
||||
|
||||
private JSONObject readJSON(ZipInputStream zipInputStream) throws IOException, JSONException {
|
||||
return new JSONObject(read(zipInputStream));
|
||||
}
|
||||
|
||||
private HashMap<String, HashMap<String, Object>> appendToLoyaltyCardHashMap(HashMap<String, HashMap<String, Object>> loyaltyCardHashMap, String cardID, String key, Object value) {
|
||||
HashMap<String, Object> loyaltyCardData = loyaltyCardHashMap.get(cardID);
|
||||
if (loyaltyCardData == null) {
|
||||
@@ -220,7 +203,7 @@ public class StocardImporter implements Importer
|
||||
|
||||
private HashMap<String, String> parseProviders(ZipInputStream zipInputStream) throws IOException, JSONException {
|
||||
// FIXME: This is probably completely wrong, but it works for the one and only test file I have
|
||||
JSONObject jsonObject = readJSON(zipInputStream);
|
||||
JSONObject jsonObject = ZipUtils.readJSON(zipInputStream);
|
||||
|
||||
JSONArray providerIdList = jsonObject.getJSONArray("provider_id_list");
|
||||
JSONArray providerList = jsonObject.getJSONArray("provider_list");
|
||||
|
||||
Reference in New Issue
Block a user