Skip to content

Instantly share code, notes, and snippets.

@mdumrauf
Last active September 21, 2021 12:21
Show Gist options
  • Save mdumrauf/09ea61d381e8d1e46b93ff954c51f3f9 to your computer and use it in GitHub Desktop.
Save mdumrauf/09ea61d381e8d1e46b93ff954c51f3f9 to your computer and use it in GitHub Desktop.
Download + Unzip example in Android
package zzz.yyy.xxx.network.service;
import org.json.JSONObject;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.http.GET;
public interface MapsDownloadService {
@GET("appversion")
Call<JSONObject> latestAppVersion();
@GET("static/cna_pp_v1.2.zip")
Call<ResponseBody> downloadFileWithFixedUrl();
}
package zzz.yyy.xxx.network;
import java.util.concurrent.TimeUnit;
// ...
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public enum ServiceFactory {
AUTH(AuthService.class, "https://auth.xxx.yyy.zzz/"),
MAP_DOWNLOAD(MapsDownloadService.class, "https://uatapi.xxx.yyy.zzz/"),
private static final String BEARER_FORMAT = "Bearer %s";
private static final int DEFAULT_CONNECT_TIMEOUT = 60;
private static final Retrofit.Builder retrofitBuilder;
private static final OkHttpClient httpClient;
static {
OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();
if(BuildConfig.DEBUG) {
// enable logging for debug builds
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
httpClientBuilder
.addInterceptor(loggingInterceptor)
.connectTimeout(DEFAULT_CONNECT_TIMEOUT, TimeUnit.SECONDS);
}
httpClient = httpClientBuilder.build();
retrofitBuilder = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create());
}
private final Class<?> clazz;
private final String baseUrl;
ServiceFactory(Class<?> clazz, String baseUrl) {
this.clazz = clazz;
this.baseUrl = baseUrl;
}
public <T> T create() {
return create(null);
}
@SuppressWarnings("unchecked")
public <T> T create(String authorization) {
OkHttpClient baseHttpClient = httpClient;
if (authorization != null) {
baseHttpClient = httpClient.newBuilder()
.addInterceptor(new AuthorizationInterceptor(String.format(BEARER_FORMAT, authorization)))
.build();
}
return (T) retrofitBuilder
.baseUrl(this.baseUrl)
.callFactory(baseHttpClient)
.build()
.create(this.clazz);
}
}
package zzz.yyy.xxx;
// ...
@EActivity(R.layout.activity_splash)
public class SplashActivity extends AbstractActivity {
private static final String TAG = SplashActivity.class.getSimpleName();
// ...
private void startBitch() {
final String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath();
if (new File(path + "/cna/6.sqlite").exists() &&
new File(path + "/cna/18.sqlite").exists() &&
new File(path + "/cna/62.sqlite").exists() &&
new File(path + "/cna/90.sqlite").exists()) {
startForGodSake();
return;
}
clearDb(path);
status.setText("Descargando base de datos..\nNo cierre la aplicación.");
statusContainer.setVisibility(View.VISIBLE);
downloadService.downloadFileWithFixedUrl().enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if (response.isSuccessful()) {
Log.d(TAG, "server contacted and has file");
boolean writtenToDisk = writeResponseBodyToDisk(response.body());
Log.d(TAG, "file download was a success? " + writtenToDisk);
final String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath();
status.setText("Descarga finalizada");
status.postDelayed(new Runnable() {
@Override
public void run() {
status.setText("Descomprimiendo..\nNo cierre la aplicación.");
try {
unzip(new File(path + "/cna_pp_v1.2.zip"), new File(path));
status.setText("Descompresión finalizada. Iniciando..");
status.postDelayed(new Runnable() {
@Override
public void run() {
startForGodSake();
}
}, 1000);
} catch (IOException e) {
Log.e(TAG, e.getMessage(), e);
Toast.makeText(SplashActivity.this, "Ha ocurrido un error. Por favor vuelva a intentarlo.", Toast.LENGTH_SHORT).show();
clearDb(path);
finish();
}
}
}, 1000);
} else {
Log.d(TAG, "server contact failed");
clearDb(path);
status.setText("Ocurrió un error. Por favor reinicie la aplicación para volver a intentar.");
status.postDelayed(new Runnable() {
@Override
public void run() {
finish();
}
}, 1500);
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
status.setText("Ocurrió un error. Verifique su conexión y reinicie para volver a intentar.");
status.postDelayed(new Runnable() {
@Override
public void run() {
finish();
}
}, 1500);
}
});
}
private void clearDb(String path) {
new File(path + "/cna/6.sqlite").delete();
new File(path + "/cna/18.sqlite").delete();
new File(path + "/cna/62.sqlite").delete();
new File(path + "/cna/90.sqlite").delete();
}
private boolean writeResponseBodyToDisk(ResponseBody body) {
try {
String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath();
File futureStudioIconFile = new File(path + File.separator + "cna_pp_v1.2.zip");
InputStream inputStream = null;
OutputStream outputStream = null;
try {
byte[] fileReader = new byte[4096];
long fileSize = body.contentLength();
long fileSizeDownloaded = 0;
inputStream = body.byteStream();
outputStream = new FileOutputStream(futureStudioIconFile);
while (true) {
int read = inputStream.read(fileReader);
if (read == -1) {
break;
}
outputStream.write(fileReader, 0, read);
fileSizeDownloaded += read;
Log.d(TAG, "file download: " + fileSizeDownloaded + " of " + fileSize);
}
outputStream.flush();
return true;
} catch (IOException e) {
return false;
} finally {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
}
} catch (IOException e) {
return false;
}
}
public static void unzip(File zipFile, File targetDirectory) throws IOException {
ZipInputStream zis = new ZipInputStream(
new BufferedInputStream(new FileInputStream(zipFile)));
try {
ZipEntry ze;
int count;
byte[] buffer = new byte[8192];
while ((ze = zis.getNextEntry()) != null) {
File file = new File(targetDirectory, ze.getName());
File dir = ze.isDirectory() ? file : file.getParentFile();
if (!dir.isDirectory() && !dir.mkdirs())
throw new FileNotFoundException("Failed to ensure directory: " +
dir.getAbsolutePath());
if (ze.isDirectory())
continue;
FileOutputStream fout = new FileOutputStream(file);
try {
while ((count = zis.read(buffer)) != -1)
fout.write(buffer, 0, count);
} finally {
fout.close();
}
}
} finally {
zis.close();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment