Hey I'm trying do application where i check my current location and save this location in ".txt" files. My application save this location in every "user set time" seconds. And it's work. Also I want add save files to Google drive. But I don't know how. Is there any method by which I can create a folder and save ".txt" files same as i did with local folder?
public class Save extends AppCompatActivity {
boolean sms = false;
int n_seconds, n_minutes, n_sum;
private String path = Environment.getExternalStorageDirectory().toString() + "/Loc/Save";
private Button buttonStartThread;
private Handler mainHandler = new Handler();
private volatile boolean stopThread = false;
NumberPicker edit_text_input_back, edit_text_input_back_2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_background);
buttonStartThread = findViewById(R.id.button_start_thread);
edit_phone_number = findViewById(R.id.edit_phone_number);
edit_mail = findViewById(R.id.edit_email);
edit_text_input_back = (NumberPicker) findViewById(R.id.edit_text_input_back);
edit_text_input_back.setMaxValue(60);
edit_text_input_back.setMinValue(0);
edit_text_input_back.setValue(0);
edit_text_input_back_2 = (NumberPicker) findViewById(R.id.edit_text_input_back_2);
edit_text_input_back_2.setMaxValue(60);
edit_text_input_back_2.setMinValue(0);
edit_text_input_back_2.setValue(0);
edit_text_input_back.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
#Override
public void onValueChange(NumberPicker numberPicker, int i, int i1) {
n_seconds = i1;
}
});
edit_text_input_back_2.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
#Override
public void onValueChange(NumberPicker numberPicker, int i, int i1) {
n_minutes = 60 * i1;
}
});
}
public void startThread(View view) {
stopThread = false;
n_sum = n_seconds + n_minutes;
ExampleRunnable runnable = new ExampleRunnable(n_sum);
new Thread(runnable).start();
buttonStartThread.setEnabled(false);
}
public void stopThread(View view) {
stopThread = true;
buttonStartThread.setEnabled(true);
}
class ExampleRunnable implements Runnable {
int seconds;
ExampleRunnable(int seconds) {
this.seconds = seconds;
}
#Override
public void run() {
for (; ; ) {
for (int i = 0; i < seconds; i++) {
if (stopThread)
return;
if (i == n_sum-1) {
runOnUiThread(new Runnable() {
#Override
public void run() {
createDir();
createFile();
}
});
}
Log.d(TAG, "startThread: " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
private void createDir() {
File folder = new File(path);
if(!folder.exists()){
try {
folder.mkdirs();
}catch (Exception e){
Toast.makeText(getApplicationContext(), e.toString(), Toast.LENGTH_LONG).show();
}
}
}
private void createFile() {
File file = new File(path+"/"+System.currentTimeMillis()+".txt");
FileOutputStream fileOutputStream;
OutputStreamWriter outputStreamWriter;
try {
Intent intent = getIntent();
Double lat = intent.getDoubleExtra("adres", 0);
Double lon = intent.getDoubleExtra("adres2", 0);
String adr = intent.getStringExtra("adres3");
fileOutputStream = new FileOutputStream(file);
outputStreamWriter = new OutputStreamWriter(fileOutputStream);
outputStreamWriter.append("Your adress: " + adr + ". " + "Your latitude: " + lat + ", " + "longtitude: " + lon+".");
outputStreamWriter.close();
fileOutputStream.close();
}catch (Exception e){
Toast.makeText(getApplicationContext(), e.toString(), Toast.LENGTH_LONG).show();
}
}
}
}
Thank you in advance
There are ample sources you can check for creating a folder, and uploading a file to Google Drive
Creating Folder
File fileMetadata = new File();
fileMetadata.setName("Invoices");
fileMetadata.setMimeType("application/vnd.google-apps.folder");
File file = driveService.files().create(fileMetadata)
.setFields("id")
.execute();
System.out.println("Folder ID: " + file.getId());
Uploading File
File fileMetadata = new File();
fileMetadata.setName("photo.jpg");
java.io.File filePath = new java.io.File("files/photo.jpg");
FileContent mediaContent = new FileContent("image/jpeg", filePath);
File file = driveService.files().create(fileMetadata, mediaContent)
.setFields("id")
.execute();
System.out.println("File ID: " + file.getId());
For the specific mime type of a txt file, you might need to refer this StackOverflow post (text/plain). For specific Google applications mime types, please see documentation.
Related
In my application I want create screen recorder and I want save it into storage!
For this I create service and write some code!
But after run service, Immediately stop it and show me Recorder stop toast!
I write below code into service :
Handler mHandler = new Handler(Looper.getMainLooper()) {
#Override
public void handleMessage(Message message) {
Log.e("ServiceErrors","RecorderService - Handler : " + message.getData().toString());
Toast.makeText(RecorderService.this, "Recorder stop", Toast.LENGTH_SHORT).show();
}
};
/* Its weird that android does not index the files immediately once its created and that causes
* trouble for user in finding the video in gallery. Let's explicitly announce the file creation
* to android and index it */
private void indexFile() {
//Create a new ArrayList and add the newly created video file path to it
ArrayList<String> toBeScanned = new ArrayList<>();
toBeScanned.add(SAVEPATH);
String[] toBeScannedStr = new String[toBeScanned.size()];
toBeScannedStr = toBeScanned.toArray(toBeScannedStr);
//Request MediaScannerConnection to scan the new file and index it
MediaScannerConnection.scanFile(this, toBeScannedStr, null, (path, uri) -> {
//Show toast on main thread
Message message = mHandler.obtainMessage();
Log.e("ServiceErrors","RecorderService Index : " + message.toString());
message.sendToTarget();
stopSelf();
});
}
//Stop and destroy all the objects used for screen recording
private void destroyMediaProjection() {
this.mAudioManager.setParameters("screenRecordAudioSource=-1");
try {
mMediaRecorder.stop();
indexFile();
} catch (RuntimeException e) {
if (new File(SAVEPATH).delete())
Toast.makeText(this, "ذخیره ویدیو با مشکل روبرو شد", Toast.LENGTH_SHORT).show();
} finally {
mMediaRecorder.reset();
mVirtualDisplay.release();
mMediaRecorder.release();
if (mMediaProjection != null) {
mMediaProjection.unregisterCallback(mMediaProjectionCallback);
mMediaProjection.stop();
mMediaProjection = null;
}
stopSelf();
}
isRecording = false;
}
UPDATE
Save to storage location code :
public void getValues() {
String res = getResolution();
setWidthHeight(res);
FPS = 25;
//BITRATE = 7130317;
BITRATE = 5530317;
audioRecSource = "1";
//saveLocation = Environment.getExternalStorageDirectory() + File.separator + ConstKeys.APPDIR + APPDIR_ORIGINAL;
saveLocation = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)
+ File.separator + ConstKeys.APPDIR + APPDIR_ORIGINAL;
File saveDir = new File(saveLocation);
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED) && !saveDir.isDirectory()) {
saveDir.mkdirs();
}
String saveFileName = getFileSaveName();
SAVEPATH = saveLocation + File.separator + saveFileName + ".mp4";
}
How can I fix it? Please help me <3
On Android 11+ you cannot save video files in a picture directory.
So no .mp4 in public DCIM directory.
I need to download mp3 file from server using retrofit.using enqueue() method ,the response callback comes in UI thread. So I decide to use execute() method from a worker thread. But my requirement is , I need to download multiple mp3 files in parallel. below is my code , Can u please let me know if it is a good practice or please suggest me a better approach.
#Override
public void onClick(View v) {
final DownloadAndStoreMusic downloadAndStoreMusic = new DownloadAndStoreMusic(this);
new Thread(new Runnable() {
#Override
public void run() {
downloadAndStoreMusic.downloadLoadMusic(musicUrlForPerseFromServer, musicUrlforLocalStorage, actionString,categoryIndex,itemIndex);
}
}).start();
}
On the Downloading class
public class DownloadAndStoreMusic {
private static final String TAG = "tag";
ApiInterfaceforMusicPersing apiInterfaceforMusicPersing;
Context mContext;
DownloadAndStoreMusic(Context mContext) {
apiInterfaceforMusicPersing = RetrofitApiClientForMusicPersing.getClient().create(ApiInterfaceforMusicPersing.class);
this.mContext = mContext;
}
public void downloadLoadMusic(final String musicUrlForPerseFromServer, final String musicUrlforLocalStorage, final String actionString,final int categoryIndex, final int itemIndex) {
/* String[] split = url.split("/");
final String pathToLocalStorage = url; // We bought music location with category path
String musicLink = split[1];*/
Log.e("server", musicUrlForPerseFromServer);
Log.e("perse", musicUrlforLocalStorage);
Call<ResponseBody> responseBodyCall = apiInterfaceforMusicPersing.downloadMusic(musicUrlForPerseFromServer);
/* responseBodyCall.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, final Response<ResponseBody> response) {
Log.e("music", "completed");
new Thread(new Runnable() {
#Override
public void run() {
writeResponseBodyToDisk(response.body(), musicUrlforLocalStorage, musicUrlForPerseFromServer, actionString,categoryIndex,itemIndex);
}
}).start();
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Toast.makeText(mContext, "Problem downloading audio", Toast.LENGTH_SHORT).show();
}
});*/
try
{
Response<ResponseBody> execute = responseBodyCall.execute();
ResponseBody body = execute.body();
writeResponseBodyToDisk(body, musicUrlforLocalStorage, musicUrlForPerseFromServer, actionString,categoryIndex,itemIndex);
}
catch (Exception e)
{
Toast.makeText(mContext, "Problem downloading audio", Toast.LENGTH_SHORT).show();
Log.e("exception"," : "+e+ " , "+musicUrlforLocalStorage);
}
}
private boolean writeResponseBodyToDisk(ResponseBody body, String pathToLocalStorage, String musicUrlForPerseFromServer, String actionString, int categoryIndex, int itemIndex) {
try {
// todo change the file location/name according to your needs
/* File audioParentDirectory;
String[] split = musicUrlForPerseFromServer.split("/");
String parentPath = split[0];
String audioName = split[1];
audioParentDirectory = new File(MyConstants.FILE_AUDIO_DIRECTORY, parentPath);
File parent = new File(audioParentDirectory,parentPath);
Log.e("audioparent",audioParentDirectory.getAbsolutePath());*/
File audioDirectory = new File(pathToLocalStorage);
Log.e("file", audioDirectory.getAbsolutePath());
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(audioDirectory);
while (true) {
int read = inputStream.read(fileReader);
if (read == -1) {
break;
}
outputStream.write(fileReader, 0, read);
fileSizeDownloaded += read;
Log.e(TAG, "file download: " + fileSizeDownloaded + " of " + fileSize);
}
outputStream.flush();
Log.e("music","music downloaded : "+ audioDirectory.getAbsolutePath());
}
}
return false;
}
Your approach is correct you will download multiply mp3 files as you expected.
I have the following Java code which downloads an image from an URL.
I can see the image downloaded in the folder, but the image does not appear in gallery. Only if I restart phone, Samsung S7 with android 7, I can see images in gallery. What can I do to have the images in gallery in real time after I downloaded them?
public class DetailsImgActivity extends AppCompatActivity {
private static final String TAG = "DetailsImgActivity";
private ImageView imageViewPoze;
private Button buttonDownload;
private static final int PERMISSION_REQUEST_CODE = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_details_img);
if (ContextCompat.checkSelfPermission(this,
android.Manifest.permission.WRITE_EXTERNAL_STORAGE) !=
PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_REQUEST_CODE);
}
// image url stored in imageID
final String imageId = getIntent().getStringExtra("ImageId");
imageViewPoze = findViewById(R.id.imageViewPozeC);
Picasso.get().load(imageId).into(imageViewPoze);
buttonDownload = findViewById(R.id.btn_Download_Img);
buttonDownload.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
downloadFile(imageId);
}
});
}
private void downloadFile(String url) {
Retrofit.Builder builder = new Retrofit.Builder().baseUrl("https://firebasestorage.blabla.com/");
Retrofit retrofit = builder.build();
FileDownloadClient fileDownloadClient = retrofit.create(FileDownloadClient.class);
Call<ResponseBody> call = fileDownloadClient.downloadFile(url);
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, final Response<ResponseBody> response) {
// if (response.isSuccess()) {
Log.d(TAG, "server contacted and has file");
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... voids) {
boolean writtenToDisk = writeResponseBodyToDisk(response.body());
return null;
}
}.execute();
//after the image has been downloaded -refresh gallery
**Toast.makeText(getApplicationContext(), "File downloaded with success!", Toast.LENGTH_LONG).show();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
{
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
File f = new File("file://"+ Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES));
Uri contentUri = Uri.fromFile(f);
mediaScanIntent.setData(contentUri);
sendBroadcast(mediaScanIntent);
}
else
{
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory())));
}**
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.e(TAG, "error");
}
});
}
private boolean writeResponseBodyToDisk(ResponseBody body) {
try {
String folder_main = Constants.dirName;
File f = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), folder_main);
if (!f.exists()) {
f.mkdirs();
}
// todo change the file location/name according to your needs
File futureStudioIconFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM+"/"+ Constants.dirName)
+ File.separator + UUID.randomUUID()+".jpg");
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;
}
}
}
I used the follwing code, but If I don't reboot phone, I can't see the picture in gallery.
**Toast.makeText(getApplicationContext(), "File downloaded with success!", Toast.LENGTH_LONG).show();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
{
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
File f = new File("file://"+ Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES));
Uri contentUri = Uri.fromFile(f);
mediaScanIntent.setData(contentUri);
sendBroadcast(mediaScanIntent);
}
else
{
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory())));
}**
When the service starts, I call startRecording() from onStartCommand(), and when the service ends, onDestroy() is called, from which I call stoprecording(). But recorder.stop() gives me an IllegalStageException
void startRecording() {
recordList = new ArrayList<>();
mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
recordListString = mSharedPreferences.getString("RecordList", null);
if(recordListString!=null){
recordList = new ArrayList(Arrays.asList(TextUtils.split(recordListString, ",")));
}
currentFormat = Integer.parseInt(mSharedPreferences.getString("PREF_REC_LIST", "1"));
tempRecNum = mSharedPreferences.getString("TempRecNum", null);
audioManager = (AudioManager)getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
recorder = new MediaRecorder();
audioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL,
audioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL),0);
if (error){
recorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
}else {
recorder.setAudioSource(MediaRecorder.AudioSource.VOICE_CALL);
}
cleanDate = System.currentTimeMillis();
recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
//recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);
/**recorder.setAudioEncodingBitRate(16);
recorder.setAudioSamplingRate(96000);**/
recorder.setOutputFile(getFilename());
recorder.setOnErrorListener(errorListener);
recorder.setOnInfoListener(infoListener);
try {
recorder.prepare();
recorder.start();
mSharedPreferences.edit().putBoolean("isRecording", true).apply();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}catch (RuntimeException e) {
File filepath = Environment.getExternalStorageDirectory();
File file = new File(filepath, AUDIO_RECORDER_FOLDER);
String tempPath = file.getAbsolutePath();
if(contactExists) {
boolean err = new File(tempPath + "/" +
getContactDisplayNameByNumber(tempRecNum, this)+"___"+
tempRecNum+"|__"+recCount+file_exts[currentFormat]).delete();
recordList.remove(recordList.size()-1);
}else{
boolean err = new File(tempPath + "/" +
"___"+tempRecNum+"|__"+recCount+file_exts[currentFormat]).delete();
recordList.remove(recordList.size()-1);
}
error = true;
startRecording();
}
}
private String getFilename() {
File filepath = Environment.getExternalStorageDirectory();
File file = new File(filepath, AUDIO_RECORDER_FOLDER);
if(!file.exists()){
file.mkdir();
}
path = file.getAbsolutePath() + "/";
if(contactExists(this, tempRecNum, getContentResolver())) {
contactExists = true;
fileName = getContactDisplayNameByNumber(tempRecNum, this)+
"___"+tempRecNum+"|__"+recCount+file_exts[currentFormat];
recordList.add(fileName);
return (path + "/" + fileName);
}else {
contactExists = false;
fileName = "___"+tempRecNum+"|__"+recCount+file_exts[currentFormat];
recordList.add(fileName);
return (path + "/" + fileName);
}
}
private MediaRecorder.OnErrorListener errorListener = new MediaRecorder.OnErrorListener() {
#Override
public void onError(MediaRecorder mr, int what, int extra) {
PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).
edit().putBoolean("isRecording", false).apply();
Toast.makeText(RecorderService.this,
"Error: " + what + ", " + extra, Toast.LENGTH_SHORT).show();
}
};
private MediaRecorder.OnInfoListener infoListener = new MediaRecorder.OnInfoListener() {
#Override
public void onInfo(MediaRecorder mr, int what, int extra) {
Toast.makeText(RecorderService.this,
"Warning: " + what + ", " + extra, Toast.LENGTH_SHORT)
.show();
}
};
#Override public void onDestroy(){
stopRecording();
super.onDestroy();
}
void stopRecording(){
try{
if (recorder != null) {
mSharedPreferences.edit().putString("RecordList", TextUtils.join(",", recordList)).apply();
mSharedPreferences.edit().putInt("RecCount", recCount+1).apply();
recorder.stop(); //This is where the error is thrown.
recorder.release();
recorder = null;
}
}catch(RuntimeException stopException){
stopException.printStackTrace();
}
}
i want to extract my .obb file contents which contain zip file for .zim file and want to extract these files into my sd card. how can I do that I tried the following way with java helperclass?
Is that correct?
public class MainActivity extends Activity implements IDownloaderClient {
private static final String LOG_TAG = "LVLDownloader";
private ProgressBar mPB;
private TextView mStatusText;
private TextView mProgressFraction;
private TextView mProgressPercent;
private TextView mAverageSpeed;
private TextView mTimeRemaining;
private View mDashboard;
private View mCellMessage;
private Button mPauseButton;
private Button mWiFiSettingsButton;
private boolean mStatePaused;
private int mState;
private IDownloaderService mRemoteService;
private IStub mDownloaderClientStub;
private void setState(int newState) {
if (mState != newState) {
mState = newState;
mStatusText.setText(Helpers.getDownloaderStringResourceIDFromState(newState));
}
}
private void setButtonPausedState(boolean paused) {
mStatePaused = paused;
int stringResourceID = paused ? R.string.text_button_resume :
R.string.text_button_pause;
mPauseButton.setText(stringResourceID);
}
/**
* This is a little helper class that demonstrates simple testing of an
* Expansion APK file delivered by Market. You may not wish to hard-code
* things such as file lengths into your executable... and you may wish to
* turn this code off during application development.
*/
private static class XAPKFile {
public final boolean mIsMain;
public final int mFileVersion;
public final long mFileSize;
XAPKFile(boolean isMain, int fileVersion, long fileSize) {
mIsMain = isMain;
mFileVersion = fileVersion;
mFileSize = fileSize;
}
}
/**
* Here is where you place the data that the validator will use to determine
* if the file was delivered correctly. This is encoded in the source code
* so the application can easily determine whether the file has been
* properly delivered without having to talk to the server. If the
* application is using LVL for licensing, it may make sense to eliminate
* these checks and to just rely on the server.
*/
private static final XAPKFile[] xAPKS = {
new XAPKFile(
true, // true signifies a main file
4, // the version of the APK that the file was uploaded
// against
240000L // the length of the file in bytes
),
new XAPKFile(
true, // false signifies a patch file
3, // the version of the APK that the patch file was uploaded
// against
24000L // the length of the patch file in bytes
)
};
/**
* Go through each of the APK Expansion files defined in the structure above
* and determine if the files are present and match the required size. Free
* applications should definitely consider doing this, as this allows the
* application to be launched for the first time without having a network
* connection present. Paid applications that use LVL should probably do at
* least one LVL check that requires the network to be present, so this is
* not as necessary.
*
* #return true if they are present.
*/
boolean expansionFilesDelivered() {
for (XAPKFile xf : xAPKS) {
String fileName = Helpers.getExpansionAPKFileName(this, xf.mIsMain, xf.mFileVersion);
if (!Helpers.doesFileExist(this, fileName, xf.mFileSize, false))
return false;
}
return true;
}
/**
* Calculating a moving average for the validation speed so we don't get
* jumpy calculations for time etc.
*/
static private final float SMOOTHING_FACTOR = 0.005f;
/**
* Used by the async task
*/
private boolean mCancelValidation;
/**
* Go through each of the Expansion APK files and open each as a zip file.
* Calculate the CRC for each file and return false if any fail to match.
*
* #return true if XAPKZipFile is successful
*/
void validateXAPKZipFiles() {
AsyncTask<Object, DownloadProgressInfo, Boolean> validationTask = new AsyncTask<Object, DownloadProgressInfo, Boolean>() {
#Override
protected void onPreExecute() {
mDashboard.setVisibility(View.VISIBLE);
mCellMessage.setVisibility(View.GONE);
mStatusText.setText(R.string.text_verifying_download);
mPauseButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mCancelValidation = true;
}
});
mPauseButton.setText(R.string.text_button_cancel_verify);
super.onPreExecute();
}
#Override
protected Boolean doInBackground(Object... params) {
for (XAPKFile xf : xAPKS) {
String fileName = Helpers.getExpansionAPKFileName(
MainActivity.this,
xf.mIsMain, xf.mFileVersion);
if (!Helpers.doesFileExist(MainActivity.this, fileName,
xf.mFileSize, false))
return false;
fileName = Helpers
.generateSaveFileName(MainActivity.this, fileName);
ZipResourceFile zrf;
byte[] buf = new byte[1024 * 256];
try {
zrf = new ZipResourceFile(fileName);
ZipEntryRO[] entries = zrf.getAllEntries();
/**
* First calculate the total compressed length
*/
long totalCompressedLength = 0;
for (ZipEntryRO entry : entries) {
totalCompressedLength += entry.mCompressedLength;
}
float averageVerifySpeed = 0;
long totalBytesRemaining = totalCompressedLength;
long timeRemaining;
/**
* Then calculate a CRC for every file in the Zip file,
* comparing it to what is stored in the Zip directory.
* Note that for compressed Zip files we must extract
* the contents to do this comparison.
*/
for (ZipEntryRO entry : entries) {
if (-1 != entry.mCRC32) {
long length = entry.mUncompressedLength;
CRC32 crc = new CRC32();
DataInputStream dis = null;
try {
dis = new DataInputStream(
zrf.getInputStream(entry.mFileName));
long startTime = SystemClock.uptimeMillis();
while (length > 0) {
int seek = (int) (length > buf.length ? buf.length
: length);
dis.readFully(buf, 0, seek);
crc.update(buf, 0, seek);
length -= seek;
long currentTime = SystemClock.uptimeMillis();
long timePassed = currentTime - startTime;
if (timePassed > 0) {
float currentSpeedSample = (float) seek
/ (float) timePassed;
if (0 != averageVerifySpeed) {
averageVerifySpeed = SMOOTHING_FACTOR
* currentSpeedSample
+ (1 - SMOOTHING_FACTOR)
* averageVerifySpeed;
} else {
averageVerifySpeed = currentSpeedSample;
}
totalBytesRemaining -= seek;
timeRemaining = (long) (totalBytesRemaining / averageVerifySpeed);
this.publishProgress(
new DownloadProgressInfo(
totalCompressedLength,
totalCompressedLength
- totalBytesRemaining,
timeRemaining,
averageVerifySpeed)
);
}
startTime = currentTime;
if (mCancelValidation)
return true;
}
if (crc.getValue() != entry.mCRC32) {
Log.e(Constants.TAG,
"CRC does not match for entry: "
+ entry.mFileName);
Log.e(Constants.TAG,
"In file: " + entry.getZipFileName());
return false;
}
} finally {
if (null != dis) {
dis.close();
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
return true;
}
#Override
protected void onProgressUpdate(DownloadProgressInfo... values) {
onDownloadProgress(values[0]);
super.onProgressUpdate(values);
}
#Override
protected void onPostExecute(Boolean result) {
if (result) {
mDashboard.setVisibility(View.VISIBLE);
mCellMessage.setVisibility(View.GONE);
mStatusText.setText(R.string.text_validation_complete);
mPauseButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
finish();
}
});
mPauseButton.setText(android.R.string.ok);
} else {
mDashboard.setVisibility(View.VISIBLE);
mCellMessage.setVisibility(View.GONE);
mStatusText.setText(R.string.text_validation_failed);
mPauseButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
finish();
}
});
mPauseButton.setText(android.R.string.cancel);
}
super.onPostExecute(result);
}
};
validationTask.execute(new Object());
}
/**
* If the download isn't present, we initialize the download UI. This ties
* all of the controls into the remote service calls.
*/
private void initializeDownloadUI() {
mDownloaderClientStub = DownloaderClientMarshaller.CreateStub
(this, ExpansionFileDownloaderService.class);
setContentView(R.layout.activity_main);
mPB = (ProgressBar) findViewById(R.id.progressBar);
mStatusText = (TextView) findViewById(R.id.statusText);
mProgressFraction = (TextView) findViewById(R.id.progressAsFraction);
mProgressPercent = (TextView) findViewById(R.id.progressAsPercentage);
mAverageSpeed = (TextView) findViewById(R.id.progressAverageSpeed);
mTimeRemaining = (TextView) findViewById(R.id.progressTimeRemaining);
mDashboard = findViewById(R.id.downloaderDashboard);
mCellMessage = findViewById(R.id.approveCellular);
mPauseButton = (Button) findViewById(R.id.pauseButton);
mWiFiSettingsButton = (Button) findViewById(R.id.wifiSettingsButton);
mPauseButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (mStatePaused) {
mRemoteService.requestContinueDownload();
} else {
mRemoteService.requestPauseDownload();
}
setButtonPausedState(!mStatePaused);
}
});
mWiFiSettingsButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
}
});
Button resumeOnCell = (Button) findViewById(R.id.resumeOverCellular);
resumeOnCell.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mRemoteService.setDownloadFlags(IDownloaderService.FLAGS_DOWNLOAD_OVER_CELLULAR);
mRemoteService.requestContinueDownload();
mCellMessage.setVisibility(View.GONE);
}
});
}
/**
* Called when the activity is first create; we wouldn't create a layout in
* the case where we have the file and are moving to another activity
* without downloading.
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/**
* Both downloading and validation make use of the "download" UI
*/
initializeDownloadUI();
/**
* Before we do anything, are the files we expect already here and
* delivered (presumably by Market) For free titles, this is probably
* worth doing. (so no Market request is necessary)
*/
if (!expansionFilesDelivered()) {
try {
Intent launchIntent = MainActivity.this
.getIntent();
Intent intentToLaunchThisActivityFromNotification = new Intent(
MainActivity
.this, MainActivity.this.getClass());
intentToLaunchThisActivityFromNotification.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_CLEAR_TOP);
intentToLaunchThisActivityFromNotification.setAction(launchIntent.getAction());
if (launchIntent.getCategories() != null) {
for (String category : launchIntent.getCategories()) {
intentToLaunchThisActivityFromNotification.addCategory(category);
}
}
// Build PendingIntent used to open this activity from
// Notification
PendingIntent pendingIntent = PendingIntent.getActivity(
MainActivity.this,
0, intentToLaunchThisActivityFromNotification,
PendingIntent.FLAG_UPDATE_CURRENT);
// Request to start the download
int startResult = DownloaderClientMarshaller.startDownloadServiceIfRequired(this,
pendingIntent, ExpansionFileDownloaderService.class);
if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) {
// The DownloaderService has started downloading the files,
// show progress
initializeDownloadUI();
return;
} // otherwise, download not needed so we fall through to
// starting the movie
} catch (NameNotFoundException e) {
Log.e(LOG_TAG, "Cannot find own package! MAYDAY!");
e.printStackTrace();
}
} else {
validateXAPKZipFiles();
}
}
/**
* Connect the stub to our service on start.
*/
#Override
protected void onStart() {
if (null != mDownloaderClientStub) {
mDownloaderClientStub.connect(this);
}
super.onStart();
}
/**
* Disconnect the stub from our service on stop
*/
#Override
protected void onStop() {
if (null != mDownloaderClientStub) {
mDownloaderClientStub.disconnect(this);
}
super.onStop();
}
/**
* Critical implementation detail. In onServiceConnected we create the
* remote service and marshaler. This is how we pass the client information
* back to the service so the client can be properly notified of changes. We
* must do this every time we reconnect to the service.
*/
#Override
public void onServiceConnected(Messenger m) {
mRemoteService = DownloaderServiceMarshaller.CreateProxy(m);
mRemoteService.onClientUpdated(mDownloaderClientStub.getMessenger());
}
/**
* The download state should trigger changes in the UI --- it may be useful
* to show the state as being indeterminate at times. This sample can be
* considered a guideline.
*/
#Override
public void onDownloadStateChanged(int newState) {
setState(newState);
boolean showDashboard = true;
boolean showCellMessage = false;
boolean paused;
boolean indeterminate;
switch (newState) {
case IDownloaderClient.STATE_IDLE:
// STATE_IDLE means the service is listening, so it's
// safe to start making calls via mRemoteService.
paused = false;
indeterminate = true;
break;
case IDownloaderClient.STATE_CONNECTING:
case IDownloaderClient.STATE_FETCHING_URL:
showDashboard = true;
paused = false;
indeterminate = true;
break;
case IDownloaderClient.STATE_DOWNLOADING:
paused = false;
showDashboard = true;
indeterminate = false;
break;
case IDownloaderClient.STATE_FAILED_CANCELED:
case IDownloaderClient.STATE_FAILED:
case IDownloaderClient.STATE_FAILED_FETCHING_URL:
case IDownloaderClient.STATE_FAILED_UNLICENSED:
paused = true;
showDashboard = false;
indeterminate = false;
break;
case IDownloaderClient.STATE_PAUSED_NEED_CELLULAR_PERMISSION:
case IDownloaderClient.STATE_PAUSED_WIFI_DISABLED_NEED_CELLULAR_PERMISSION:
showDashboard = false;
paused = true;
indeterminate = false;
showCellMessage = true;
break;
case IDownloaderClient.STATE_PAUSED_BY_REQUEST:
paused = true;
indeterminate = false;
break;
case IDownloaderClient.STATE_PAUSED_ROAMING:
case IDownloaderClient.STATE_PAUSED_SDCARD_UNAVAILABLE:
paused = true;
indeterminate = false;
break;
case IDownloaderClient.STATE_COMPLETED:
showDashboard = false;
paused = false;
indeterminate = false;
validateXAPKZipFiles();
return;
default:
paused = true;
indeterminate = true;
showDashboard = true;
}
int newDashboardVisibility = showDashboard ? View.VISIBLE : View.GONE;
if (mDashboard.getVisibility() != newDashboardVisibility) {
mDashboard.setVisibility(newDashboardVisibility);
}
int cellMessageVisibility = showCellMessage ? View.VISIBLE : View.GONE;
if (mCellMessage.getVisibility() != cellMessageVisibility) {
mCellMessage.setVisibility(cellMessageVisibility);
}
mPB.setIndeterminate(indeterminate);
setButtonPausedState(paused);
}
/**
* Sets the state of the various controls based on the progressinfo object
* sent from the downloader service.
*/
#Override
public void onDownloadProgress(DownloadProgressInfo progress) {
mAverageSpeed.setText(getString(R.string.kilobytes_per_second,
Helpers.getSpeedString(progress.mCurrentSpeed)));
mTimeRemaining.setText(getString(R.string.time_remaining,
Helpers.getTimeRemaining(progress.mTimeRemaining)));
progress.mOverallTotal = progress.mOverallTotal;
mPB.setMax((int) (progress.mOverallTotal >> 8));
mPB.setProgress((int) (progress.mOverallProgress >> 8));
mProgressPercent.setText(Long.toString(progress.mOverallProgress
* 100 /
progress.mOverallTotal) + "%");
mProgressFraction.setText(Helpers.getDownloadProgressString
(progress.mOverallProgress,
progress.mOverallTotal));
try {
ZipResourceFile expansionFile = APKExpansionSupport
.getAPKExpansionZipFile(this, 4, 0);
ZipEntryRO[] zip = expansionFile.getAllEntries();
Log.e("", "zip[0].isUncompressed() : " + zip[0].isUncompressed());
Log.e("",
"mFile.getAbsolutePath() : "
+ zip[0].mFile.getAbsolutePath());
Log.e("", "mFileName : " + zip[0].mFileName);
Log.e("", "mZipFileName : " + zip[0].mZipFileName);
Log.e("", "mCompressedLength : " + zip[0].mCompressedLength);
File file = new File(Environment.getExternalStorageDirectory()
.getAbsolutePath() + "");
ZipHelper.unzip(zip[0].mZipFileName, file);
if (file.exists()) {
Log.e("", "unzipped : " + file.getAbsolutePath());
}
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
protected void onDestroy() {
this.mCancelValidation = true;
super.onDestroy();
}
}
try {
ZipResourceFile expansionFile = APKExpansionSupport
.getAPKExpansionZipFile(this, 4, 0);
ZipEntryRO[] zip = expansionFile.getAllEntries();
Log.e("", "zip[0].isUncompressed() : " + zip[0].isUncompressed());
Log.e("",
"mFile.getAbsolutePath() : "
+ zip[0].mFile.getAbsolutePath());
Log.e("", "mFileName : " + zip[0].mFileName);
Log.e("", "mZipFileName : " + zip[0].mZipFileName);
Log.e("", "mCompressedLength : " + zip[0].mCompressedLength);
File file = new File(Environment.getExternalStorageDirectory()
.getAbsolutePath() + "");
ZipHelper.unzip(zip[0].mZipFileName, file);
if (file.exists()) {
Log.e("", "unzipped : " + file.getAbsolutePath());
}
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
protected void onDestroy() {
this.mCancelValidation = true;
super.onDestroy();
}
and use java helper class.
public class ZipHelper {
static boolean zipError = false;
public static boolean isZipError() {
return zipError;
}
public static void setZipError(boolean zipError) {
ZipHelper.zipError = zipError;
}
public static void unzip(String archive, File outputDir) {
try {
Log.d("control", "ZipHelper.unzip() - File: " + archive);
ZipFile zipfile = new ZipFile(archive);
for (Enumeration<? extends ZipEntry> e = zipfile.entries(); e
.hasMoreElements();) {
ZipEntry entry = (ZipEntry) e.nextElement();
unzipEntry(zipfile, entry, outputDir);
}
} catch (Exception e) {
Log.d("control", "ZipHelper.unzip() - Error extracting file "
+ archive + ": " + e);
setZipError(true);
}
}
private static void unzipEntry(ZipFile zipfile, ZipEntry entry,
File outputDir) throws IOException {
if (entry.isDirectory()) {
createDirectory(new File(outputDir, entry.getName()));
return;
}
File outputFile = new File(outputDir, entry.getName());
if (!outputFile.getParentFile().exists()) {
createDirectory(outputFile.getParentFile());
}
Log.d("control", "ZipHelper.unzipEntry() - Extracting: " + entry);
BufferedInputStream inputStream = new BufferedInputStream(
zipfile.getInputStream(entry));
BufferedOutputStream outputStream = new BufferedOutputStream(
new FileOutputStream(outputFile));
try {
IOUtils.copy(inputStream, outputStream);
} catch (Exception e) {
Log.d("control", "ZipHelper.unzipEntry() - Error: " + e);
setZipError(true);
} finally {
outputStream.close();
inputStream.close();
}
}
private static void createDirectory(File dir) {
Log.d("control",
"ZipHelper.createDir() - Creating directory: " + dir.getName());
if (!dir.exists()) {
if (!dir.mkdirs())
throw new RuntimeException("Can't create directory " + dir);
} else
Log.d("control",
"ZipHelper.createDir() - Exists directory: "
+ dir.getName());
}
}
Use this helper class to unzip the obb
package com.example.dummy;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import android.util.Log;
public class ZipHelper
{
boolean zipError=false;
public boolean isZipError() {
return zipError;
}
public void setZipError(boolean zipError) {
this.zipError = zipError;
}
public void unzip(String archive, File outputDir)
{
try {
ZipFile zipfile = new ZipFile(archive);
//AvazAppActivity.printLog("TOTAL ZIP ENTRIES",zipfile.size()+":");
for (Enumeration e = zipfile.entries(); e.hasMoreElements(); ) {
ZipEntry entry = (ZipEntry) e.nextElement();
unzipEntry(zipfile, entry, outputDir);
}
}
catch (Exception e) {
setZipError(true);
}
}
private void unzipEntry(ZipFile zipfile, ZipEntry entry, File outputDir) throws IOException
{
if (entry.isDirectory()) {
createDirectory(new File(outputDir, entry.getName()));
return;
}
File outputFile = new File(outputDir, entry.getName());
if (!outputFile.getParentFile().exists()){
createDirectory(outputFile.getParentFile());
}
//AvazAppActivity.printLog("control","ZipHelper.unzipEntry() - Extracting: " + entry);
BufferedInputStream inputStream = new BufferedInputStream(zipfile.getInputStream(entry));
BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(outputFile));
try {
copy(inputStream, outputStream);
}
catch (Exception e) {
setZipError(true);
}
finally {
outputStream.close();
inputStream.close();
}
}
private void createDirectory(File dir)
{
if (!dir.exists()){
if(!dir.mkdirs()) throw new RuntimeException("Can't create directory "+dir);
}
else
Log.d("control","ZipHelper.createDir() - Exists directory: "+dir.getName());
}
private void copy(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024];
int read;
while((read = in.read(buffer)) != -1){
out.write(buffer, 0, read);
}
}
}
In your class to unzip the obb use the below snippet.
ZipHelper helper = new ZipHelper();
File file = new File("/sdcard/Android/data/"+PACKAGE_NAME+"/");
helper.unzip("/sdcard/Android/obb/"+PACKAGE_NAME+"/main."+ versionCode + "."+PACKAGE_NAME+".obb", file);
this code will extract the obb content in data folder.