a way to copy from google drive? [duplicate] - android

I am developing an app to uploading ,displaying and downloading files from G Drive. Unfortunately When downloading I am getting
com.google.api.client.http.HttpResponseException: 401 Unauthorized.
Please help me to solve this problem.
Here I am assigning
credential = GoogleAccountCredential.usingOAuth2(this,DriveScopes.DRIVE);
service=new Drive.Builder(AndroidHttp.newCompatibleTransport(),new GsonFactory(),credential).build();
My Code Is:
package com.example.googledrive;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import com.google.api.client.extensions.android.http.AndroidHttp;
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential;
import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException;
import com.google.api.client.http.FileContent;
import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.HttpResponse;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.Drive.Children;
import com.google.api.services.drive.Drive.Files;
import com.google.api.services.drive.Drive.Files.Get;
import com.google.api.services.drive.DriveScopes;
import com.google.api.services.drive.model.ChildList;
import com.google.api.services.drive.model.ChildReference;
import com.google.api.services.drive.model.File;
import com.google.api.services.drive.model.FileList;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.StrictMode;
import android.provider.MediaStore;
import android.accounts.AccountManager;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
public class MainActivity extends Activity {
static final int REQUEST_ACCOUNT_PICKER = 1;
static final int REQUEST_AUTHORIZATION = 2;
static final int CAPTURE_IMAGE = 3;
private static Uri fileUri;
private static Drive service;
private ProgressDialog progressDialog;
private GoogleAccountCredential credential;
String fileId;
String fileName;
String downloadUrl;
ListView listView;
Activity activity;
String sdCardPadth;
List<File> allFileList;
ArrayList<String> fileType;
ArrayList<String> mainTitleList;
ArrayList<String> fileIdList;
ArrayList<String> alternateUrlList;
ArrayList<Integer> fileSizeList;
FileTitlesAdapter myAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.uploadedFilesList);
allFileList = new ArrayList<File>();
mainTitleList = new ArrayList<String>();
alternateUrlList = new ArrayList<String>();
fileSizeList = new ArrayList<Integer>();
fileType = new ArrayList<String>();
fileIdList=new ArrayList<String>();
progressDialog=new ProgressDialog(getApplicationContext());
progressDialog.setTitle("Please Wait....");
progressDialog.setCancelable(false);
activity = this;
credential = GoogleAccountCredential.usingOAuth2(this,DriveScopes.DRIVE);
startActivityForResult(credential.newChooseAccountIntent(),REQUEST_ACCOUNT_PICKER);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> arg0, View view, final int arg2,long arg3) {
// String str=itemArray.get(arg2).toString().trim();
System.out.println("mainTitleList size==="+mainTitleList.size());
System.out.println("arg2==="+arg2);
fileName = (String)mainTitleList.get(arg2);
mainTitleList.clear();
//fileSizeList.clear();
final String fileTypeStr=fileType.get(arg2);
fileType.clear();
if(fileTypeStr.contains("application/vnd.google-apps.folder"))
{
Thread t = new Thread(new Runnable() {
#Override
public void run() {
boolean b=true;
try {
String dirUrl=alternateUrlList.get(arg2);
alternateUrlList.clear();
System.out.println("Folder Name Is:"+fileName);
System.out.println("Folder Type Is:"+fileTypeStr);
System.out.println("Folder URL Is:"+dirUrl);
String fileId=fileIdList.get(arg2);
System.out.println("Folder Id Is:"+fileId);
//retrieveAllFilesFromDir(service, fileId, b);
//retrieveAllFiles1(service, b, fileId);
//Files.List request = service.children().get(fileId, null);
Files.List request = service.files().list().setQ("'" + fileId + "' in parents ");
retrieveAllFiles(service,request,b);
//retrieveAllFiles(service, b);
} catch (Exception e) {
// TODO Auto-generated catch block
System.out.println("Exception In retrieveAllFiles Dir Is:"+e);
e.printStackTrace();
}
}
});t.start();
}
else
{
try {
System.out.println("fileSizeList size===="+fileSizeList.size());
System.out.println("arg2===="+arg2);
Integer fileSize = (int) fileSizeList.get(arg2);
downloadUrl = alternateUrlList.get(arg2);
byte[] size = new byte[fileSize];
int byteRead = 0, byteWritten = 0;
sdCardPadth = Environment.getExternalStorageDirectory().getPath();
System.out.println("Download Url==="+downloadUrl);
new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
InputStream inStream=downloadFile(service, downloadUrl);
java.io.File inFile=new java.io.File(sdCardPadth+"/"+fileName+"1");
System.out.println("File Succesfully Stored");
}
}).start();
} catch (Exception e) {
// TODO Auto-generated catch block
System.out.println("Exception In get Integer Is:" + e);
e.printStackTrace();
}
}
}
});
}
#Override
protected void onActivityResult(final int requestCode,
final int resultCode, final Intent data) {
switch (requestCode) {
case REQUEST_ACCOUNT_PICKER:
if (resultCode == RESULT_OK && data != null
&& data.getExtras() != null) {
String accountName = data
.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
if (accountName != null) {
credential.setSelectedAccountName(accountName);
service = getDriveService(credential);
final boolean b=false;
Thread t=new Thread(new Runnable() {
#Override
public void run() {
try
{
Files.List request = service.files().list().setQ("hidden="+b);
retrieveAllFiles(service,request,b);
} catch (Exception e) {
System.out.println("Exception Is:"+e);
e.printStackTrace();
}
}
}) ;t.start();
}
}
break;
case REQUEST_AUTHORIZATION:
if (resultCode == Activity.RESULT_OK) {
System.out.println("REQUEST_AUTHORIZATION case Is:"
+ REQUEST_AUTHORIZATION);
saveFileToDrive();
} else {
startActivityForResult(credential.newChooseAccountIntent(),
REQUEST_ACCOUNT_PICKER);
}
break;
case CAPTURE_IMAGE:
if (resultCode == Activity.RESULT_OK) {
System.out.println("CAPTURE_IMAGE case Is:" + CAPTURE_IMAGE);
saveFileToDrive();
}
}
}
private void saveFileToDrive() {
Thread t = new Thread(new Runnable() {
#Override
public void run() {
try {
// File's binary content
System.out.println("run method");
java.io.File fileContent = new java.io.File(fileUri.getPath());
FileContent mediaContent = new FileContent("image/jpeg",fileContent);
// File's metadata.
File body = new File();
body.setTitle(fileContent.getName());
body.setMimeType("image/jpeg");
File file=null;
try {
file = service.files().insert(body, mediaContent).execute();
} catch (Exception e) {
System.out.println("Exception In Insert File Is"+e);
e.printStackTrace();
}
if (file != null) {
showToast("Photo uploaded: " + file.getTitle());
System.out.println("photo sucessfullly uploaded:"+ fileId);boolean b=false;
Files.List request = service.files().list().setQ("hidden="+b);
retrieveAllFiles(service,request,b);
}
} catch (UserRecoverableAuthIOException e) {
startActivityForResult(e.getIntent(), REQUEST_AUTHORIZATION);
} catch (IOException e) {
e.printStackTrace();
}
}
});
t.start();
}
private Drive getDriveService(GoogleAccountCredential credential) {
return new Drive.Builder(AndroidHttp.newCompatibleTransport(),
new GsonFactory(), credential).build();
}
public void showToast(final String toast) {
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), toast,Toast.LENGTH_SHORT).show();
}
});
}
private List<File> retrieveAllFiles(Drive service,Files.List request,boolean b) throws IOException {
List<File> result = new ArrayList<File>();
final ArrayList<String> titleList = new ArrayList<String>();
String fileUrl = "";
do {
try {
FileList files = request.execute();
result.addAll(files.getItems());
request.setPageToken(files.getNextPageToken());
for (int i = 0; i < result.size(); i++) {
File tempFile = result.get(i);
String fileTypeStr = tempFile.getMimeType();
String fileName = tempFile.getTitle();
titleList.add(fileName);
fileId = tempFile.getId();
fileIdList.add(fileId);
fileUrl = tempFile.getAlternateLink();
System.out.println("<><>< fileUrl Is:" + fileUrl);
alternateUrlList.add(fileUrl);
fileType.add(fileTypeStr);
mainTitleList.add(fileName);
try {
Integer fileSize =tempFile.getFileSize()==null?100:(int) (long) tempFile.getFileSize();
fileSizeList.add(fileSize);
System.out.println("<><>< fileSize Is:" + fileSize);
} catch (Exception e) {
fileSizeList.add(2000);
e.printStackTrace();
}
}
try {
runOnUiThread(new Runnable() {
public void run() {
myAdapter = new FileTitlesAdapter(activity,
fileType, mainTitleList, alternateUrlList,
fileSizeList);
listView.setAdapter(myAdapter);
}
});
} catch (Exception e) {
System.out.println("Exception Setting ListView Is:" + e);
e.printStackTrace();
}
} catch (IOException e) {
System.out.println("An error occurred in retrieveAllFiles:"+ e);
request.setPageToken(null);
}
} while (request.getPageToken() != null
&& request.getPageToken().length() > 0);
return result;
}
private static InputStream downloadFile(Drive service, String url) {
System.out.println("downloadFile is called service=="+service);
if (url != null && url.length() > 0) {
try {
System.out.println("downloadFile is called try");
HttpResponse resp =service.getRequestFactory().buildGetRequest(new GenericUrl(url)).execute();
System.out.println("resp.getContent()===="+resp.getContent());
return resp.getContent();
} catch (Exception e) {
System.out.println("Exception Is:"+e);
e.printStackTrace();
return null;
}
} else {
System.out.println("No Exception No Output");
return null;
}
}
}

This is code that I use to download File from google Drive
new AsyncTask<Void, Integer, Boolean>() {
#Override
protected Boolean doInBackground(Void... params) {
try {
File file = service.files().get("path in drive").execute();
java.io.File toFile = new java.io.File("where you want to store");
toFile.createNewFile();
HttpDownloadManager downloader = new HttpDownloadManager(file, toFile);
downloader.setListener(new HttpDownloadManager.FileDownloadProgressListener() {
public void downloadProgress(long bytesRead, long totalBytes) {
Log.i("chauster",totalBytes);
Log.i("chauster",bytesRead);
}
#Override
public void downloadFinished() {
// TODO Auto-generated method stub
}
#Override
public void downloadFailedWithError(Exception e) {
// TODO Auto-generated method stub
}
});
return downloader.download(service);
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
protected void onPostExecute(Boolean result) {
};
}.execute();
HttpDownloadManager.java
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import com.google.api.client.http.GenericUrl;
import com.google.api.client.http.HttpResponse;
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.model.File;
import com.grandex.ShareInfomation.ShareData;
import com.grandex.ShareInfomation.ShareData.ToolTapState;
public class HttpDownloadManager {
private String donwloadUrl;
private String toFile;
private FileDownloadProgressListener listener;
private long totalBytes;
public void setListener(FileDownloadProgressListener listener) {
this.listener = listener;
}
public HttpDownloadManager(File sourceFile, java.io.File destinationFile) {
super();
this.donwloadUrl = sourceFile.getDownloadUrl();
this.toFile = destinationFile.toString();
this.totalBytes = sourceFile.getFileSize();
}
public static interface FileDownloadProgressListener {
public void downloadProgress(long bytesRead, long totalBytes);
public void downloadFinished();
public void downloadFailedWithError(Exception e);
}
public boolean download(Drive service) {
HttpResponse respEntity = null;
try {
// URL url = new URL(urlString);
respEntity = service.getRequestFactory()
.buildGetRequest(new GenericUrl(donwloadUrl)).execute();
InputStream in = respEntity.getContent();
if(totalBytes == 0) {
totalBytes = respEntity.getContentLoggingLimit();
}
try {
FileOutputStream f = new FileOutputStream(toFile) {
#Override
public void write(byte[] buffer, int byteOffset,
int byteCount) throws IOException {
// TODO Auto-generated method stub
super.write(buffer, byteOffset, byteCount);
}
}
};
byte[] buffer = new byte[1024];
int len1 = 0;
long bytesRead = 0;
while ((len1 = in.read(buffer)) > 0) {
f.write(buffer, 0, len1);
if (listener != null) {
bytesRead += len1;
listener.downloadProgress(bytesRead, totalBytes);
}
}
f.close();
} catch (Exception e) {
if (listener != null) {
listener.downloadFailedWithError(e);
}
return false;
}
if (listener != null) {
listener.downloadFinished();
}
return true;
} catch (IOException ex) {
if (listener != null) {
listener.downloadFailedWithError(ex);
return false;
}
} finally {
if(respEntity != null) {
try {
respEntity.disconnect();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return false;
}
}

Nowhere in your code are you setting the Authorization header.
You need something like
setRequestProperty("Authorization", "OAuth " + "***ACCESS_TOKEN***");
For any 401/403 errors it's well worth getting your request working on the Oauth. Try this out

Please check below code for download apk file from google drive
implementation 'com.google.android.material:material:1.0.0'
Add uses permission
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
Create a file provider
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="external"
path="." />
<external-files-path
name="external_files"
path="." />
<files-path
name="files"
path="." />
Now declare the file provider inside the manifest
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="#xml/file_provider_paths" />
Add some value inside strings.xml file
<resources>
<string name="app_name">Download APK</string>
<string name="downloading">Downloading...</string>
<string name="title_file_download">APK is downloading</string>
<string name="storage_access_required">Storage access is required to downloading the file.</string>
<string name="storage_permission_denied">Storage permission request was denied.</string>
<string name="ok">OK</string>
Create a download controller
package com.hktpayment.mytmoney.pos.mauritius.util
import android.app.Dialog
import android.app.DownloadManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.database.Cursor
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.util.Log
import android.widget.ProgressBar
import android.widget.Toast
import androidx.core.content.FileProvider
import com.hktpayment.mytmoney.pos.mauritius.BuildConfig
import com.hktpayment.mytmoney.pos.mauritius.R
import java.io.File
class DownloadController(
private val context: Context,
private val url: String,
private val progressBar: Dialog
) {
companion object {
private const val FILE_NAME = "SampleDownloadApp.apk"
private const val FILE_BASE_PATH = "file://"
private const val MIME_TYPE = "application/vnd.android.package-archive"
private const val PROVIDER_PATH = ".provider"
private const val APP_INSTALL_PATH = "application/vnd.android.package-
archive"
}
private lateinit var downloadManager: DownloadManager
fun enqueueDownload() {
var destination =
context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString()
+ "/"
destination += FILE_NAME
val uri = Uri.parse("$FILE_BASE_PATH$destination")
val file = File(destination)
if (file.exists()) file.delete()
downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as
DownloadManager
val downloadUri = Uri.parse(url)
val request = DownloadManager.Request(downloadUri)
request.setMimeType(MIME_TYPE)
request.setTitle(context.getString(R.string.title_file_download))
request.setDescription(context.getString(R.string.downloading))
// set destination
request.setDestinationUri(uri)
showInstallOption(destination, uri)
// Enqueue a new download and same the referenceId
downloadManager.enqueue(request)
Toast.makeText(context, context.getString(R.string.downloading),
Toast.LENGTH_LONG)
.show()
}
private fun showInstallOption(
destination: String,
uri: Uri
) {
// set BroadcastReceiver to install app when .apk is downloaded
progressBar.show()
val onComplete = object : BroadcastReceiver() {
override fun onReceive(
context: Context,
intent: Intent
) {
progressBar.dismiss()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
val contentUri = FileProvider.getUriForFile(
context,
BuildConfig.APPLICATION_ID + PROVIDER_PATH,
File(destination)
)
val install = Intent(Intent.ACTION_VIEW)
install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
install.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
install.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true)
install.data = contentUri
context.startActivity(install)
context.unregisterReceiver(this)
// finish()
} else {
val install = Intent(Intent.ACTION_VIEW)
install.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
install.setDataAndType(
uri,
APP_INSTALL_PATH
)
context.startActivity(install)
context.unregisterReceiver(this)
// finish()
}
}
}
context.registerReceiver(onComplete, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE))
}
}
In this activity, we are checking storage permission first. If permission is granted than calling download function otherwise requesting for storage permission.
val apkUrl = "https://download .apk"
downloadController = DownloadController(this, apkUrl)
downloadController.enqueueDownload()

Related

Not able to open PDF in the app

This is a continuation from my previous quesion. I wanted to open the pdf in the app instead of opening it with third-party apps. I've rewritten the code so that pdf files in assets folder can be copied into sd card.
Here is my code:
package com.dell.pdfreader;
import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import net.sf.andpdf.pdfviewer.PdfViewerActivity;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class PdfMainActivity extends AppCompatActivity implements View.OnClickListener {
private static String TAG = PdfMainActivity.class.getCanonicalName();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pdf_main);
Button click = (Button) findViewById(R.id.click);
click.setOnClickListener(this);
}
#Override
public void onClick(View view) {
Context mContext = getApplicationContext();
switch (view.getId()) {
case R.id.click:
try {
AssetManager assetManager = getAssets();
String[] files = null;
try {
files = assetManager.list("pdffiles");
} catch (IOException e) {
Log.e(TAG, e.getMessage());
}
for (String fileName : files != null ? files : new String[0]) {
InputStream is = null;
OutputStream os = null;
try {
is = assetManager.open("pdffiles/" + fileName);
os = new FileOutputStream(Environment.getExternalStorageDirectory().toString() + "/" + fileName);
copyFile(is, os);
is.close();
os.flush();
os.close();
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
}
Uri path = Uri.parse(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "Dojo_lab_tour.pdf");
String oPath = path.toString();
Intent intent = new Intent(PdfMainActivity.this, ReaderActivity.class);
if (ContextCompat.checkSelfPermission(PdfMainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
intent.setDataAndType(path, "application/pdf");
intent.putExtra(PdfViewerActivity.EXTRA_PDFFILENAME, oPath);
startActivity(intent);
} else {
Log.d(TAG, "No permission!");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
private void copyFile(InputStream is, OutputStream os) throws IOException {
byte[] buffer = new byte[1024];
int read;
while ((read = is.read(buffer)) != -1) {
os.write(buffer, 0, read);
}
}
}
And here is my 2nd activity:
package com.dell.pdfreader;
import android.os.Bundle;
public class ReaderActivity extends net.sf.andpdf.pdfviewer.PdfViewerActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_reader);
}
#Override
public int getPreviousPageImageResource() {
return R.drawable.left_arrow;
}
#Override
public int getNextPageImageResource() {
return R.drawable.right_arrow;
}
#Override
public int getZoomInImageResource() {
return R.drawable.zoom_in;
}
#Override
public int getZoomOutImageResource() {
return R.drawable.zoom_out;
}
#Override
public int getPdfPasswordLayoutResource() {
return 0;
}
#Override
public int getPdfPageNumberResource() {
return 0;
}
#Override
public int getPdfPasswordEditField() {
return 0;
}
#Override
public int getPdfPasswordOkButton() {
return 0;
}
#Override
public int getPdfPasswordExitButton() {
return 0;
}
#Override
public int getPdfPageNumberEditField() {
return 0;
}
}
When I run that code, I get this error:
03-05 16:19:43.000 14997-14997/com.dell.pdfreader E/com.dell.pdfreader.PdfMainActivity: /storage/emulated/0/Dojo_Lab_Tour.pdf (Permission denied)
03-05 16:19:43.049 14997-14997/com.dell.pdfreader I/PDFVIEWER: onCreate
03-05 16:19:43.049 14997-14997/com.dell.pdfreader E/PDFVIEWER: restoreInstance
03-05 16:19:43.119 14997-14997/com.dell.pdfreader I/PDFVIEWER: Intent { dat=/storage/emulated/0/Dojo_lab_tour.pdf typ=application/pdf cmp=com.dell.pdfreader/.ReaderActivity (has extras) }
03-05 16:19:43.124 14997-14997/com.dell.pdfreader I/PDFVIEWER: ST='file '/storage/emulated/0/Dojo_lab_tour.pdf' not found'
In mainfest file, I've added these two lines:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
How can I fix this error?
EDIT:
My assets folder structure is as given below:
I modified my code as suggested by Tommin and Commonsware:
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
Intent intent = new Intent(PdfMainActivity.this, ReaderActivity.class);
if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
intent.setDataAndType(path, "application/pdf");
intent.putExtra(PdfViewerActivity.EXTRA_PDFFILENAME, oPath);
startActivity(intent);
} else {
Log.d(TAG, "No permission!");
}
}
Getting this error now:
03-05 17:45:26.526 7888-7888/com.dell.pdfreader E/com.dell.pdfreader.PdfMainActivity: /storage/emulated/0/Dojo_Lab_Tour.pdf (Permission denied)
1- Add the permissions in your manifest, like you did:
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.....">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
2- These 2 permissions are considered to be dangerous permissions, which you should request on the Runtime, on your onClick method for ex:
#Override
public void onClick (View view) {
if (ContextCompat.checkSelfPermission (PdfMainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED ||
ContextCompat.checkSelfPermission (PdfMainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions (PdfMainActivity.this, new String [] { Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE }, 1000);
return;
}
...
}
3- Make sure the external storage is writable before copying your stream into it:
if (!isExternalStorageWritable ()) {
throw new Exception ("External Storage Not Writable");
}
private boolean isExternalStorageWritable () {
return Environment.MEDIA_MOUNTED.equals (Environment.getExternalStorageState ());
}
4- Your code becomes:
#Override
public void onClick (View v) {
if (ContextCompat.checkSelfPermission (PdfMainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED ||
ContextCompat.checkSelfPermission (PdfMainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions (PdfMainActivity.this, new String [] { Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE }, 1000);
return;
}
AssetManager assetManager = getAssets ();
String dir = "pdffiles";
try {
String [] paths = assetManager.list (dir);
for (String path : paths) {
if (!isExternalStorageWritable ()) {
throw new Exception ("External Storage Not Writable");
}
InputStream is = assetManager.open (dir + File.separator + path);
OutputStream os = new FileOutputStream (Environment.getExternalStorageDirectory () + File.separator + path);
copy (is, os);
closeQuietly (os, is);
}
} catch (Exception e) {
// TODO Catch your exception here
}
}
public static int copy (InputStream is, OutputStream os) throws IOException {
long count = 0;
int n;
byte [] buffer = new byte [4 * 1024];
while (-1 != (n = is.read (buffer))) {
os.write (buffer, 0, n);
count += n;
}
if (count > Integer.MAX_VALUE) {
return -1;
}
return (int) count;
}
public static void closeQuietly (Closeable... closeables) {
if (closeables == null || closeables.length == 0) {
return;
}
try {
for (Closeable closeable : closeables) {
if (closeable != null) {
closeable.close ();
}
}
} catch (final IOException ignore) { }
}
5- When trying to read the PDFs, make sure the external storage is readable as well by calling:
private boolean isExternalStorageReadable() {
String state = Environment.getExternalStorageState ();
return Environment.MEDIA_MOUNTED.equals (state) || Environment.MEDIA_MOUNTED_READ_ONLY.equals (state);
}
6- Put the copy processing on a background thread not to block the UI. And maybe show a progress Popup to the user.
I got it, guys. I modified my code as:
Uri path = Uri.parse(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "EPSF.pdf");
String oPath = path.toString();
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
&& checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED ) {
ActivityCompat.requestPermissions(PdfMainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, 1000);
Log.d(TAG, "No permission!");
} else {
Intent intent1 = new Intent(PdfMainActivity.this, ReaderActivity.class);
intent1.setDataAndType(path, "application/pdf");
intent1.putExtra(PdfViewerActivity.EXTRA_PDFFILENAME, oPath);
startActivity(intent1);
}
}
I added run time permissions and modified according to what Mehdi had suggested.

No such file or directory exception in creating a file in android(using f.createNewFile())

I am trying to send an image file through android using a server socket. I have used AsyncTask class on the client side and created a TransferFile class to send the file. I am getting a NO SUCH FILE OR DIRECTORY exception while creating the file on client's side. The code is attached below.
Permissions.
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
TransferFile class.
import android.app.IntentService;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.widget.Toast;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
public class TransferFile extends IntentService{
private static final int SOCKET_TIMEOUT = 5000;
public static final String ACTION_SEND_FILE = "com.apposite.wifip2p.SEND_FILE";
public static final String EXTRAS_FILE_PATH = "file_url";
public static final String EXTRAS_GROUP_OWNER_ADDRESS = "go_host";
public static final String EXTRAS_GROUP_OWNER_PORT = "go_port";
public TransferFile(){
super("TransferFile");
}
#Override
protected void onHandleIntent(Intent intent) {
Context context = getApplicationContext();
Toast.makeText(this, "Client Socket Intent Handled.", Toast.LENGTH_SHORT).show();
if (intent.getAction().equals(ACTION_SEND_FILE)) {
Toast.makeText(context, "inside ACTION_SEND_FILE.", Toast.LENGTH_SHORT).show();
String fileUri = intent.getExtras().getString(EXTRAS_FILE_PATH);
String host = intent.getExtras().getString(EXTRAS_GROUP_OWNER_ADDRESS);
Socket socket = new Socket();
int port = intent.getExtras().getInt(EXTRAS_GROUP_OWNER_PORT);
try {
socket.bind(null);
socket.connect((new InetSocketAddress(host, port)), SOCKET_TIMEOUT);
Toast.makeText(context, "Client Socket Connected: "+socket.isConnected(), Toast.LENGTH_SHORT).show();
OutputStream stream = socket.getOutputStream();
ContentResolver cr = context.getContentResolver();
InputStream is = null;
try {
is = cr.openInputStream(Uri.parse(fileUri));
}
catch (FileNotFoundException e) {
}
MainActivity.copyFile(is, stream);
} catch (IOException e) {
Toast.makeText(context, "File can't be copied to client.", Toast.LENGTH_SHORT).show();
} finally {
if(socket.isConnected()){
try {
socket.close();
} catch (IOException e){
e.printStackTrace();
}
}
}
}
}
}
MainActivity class
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.net.wifi.WpsInfo;
import android.net.wifi.p2p.WifiP2pConfig;
import android.net.wifi.p2p.WifiP2pDevice;
import android.net.wifi.p2p.WifiP2pDeviceList;
import android.net.wifi.p2p.WifiP2pInfo;
import android.net.wifi.p2p.WifiP2pManager;
import android.os.AsyncTask;
import android.os.Environment;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity implements WifiP2pManager.PeerListListener, WifiP2pManager.ConnectionInfoListener{
WifiP2pManager wifi;
private WifiP2pInfo info;
ListView listViewPeer;
WifiP2pManager.Channel channel;
IntentFilter intentFilter = new IntentFilter();
Button discover, send;
List<WifiP2pDevice> peersList;
List<String> peersNameList;
BroadcastReceiver receiver = null;
ProgressDialog progressDialog = null;
boolean isConnected = false;
protected static final int CHOOSE_FILE_RESULT_CODE = 20;
Intent serviceIntent;
boolean isHost = true;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);
intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
intentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
listViewPeer = (ListView) findViewById(R.id.ListViewPeer);
discover = (Button) findViewById(R.id.btnDiscover);
send = (Button) findViewById(R.id.btnGallery);
wifi = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
channel = wifi.initialize(this, getMainLooper(), null);
receiver = new WifiP2pBroadcastReceiver(wifi, channel, this);
peersList = new ArrayList<>();
peersNameList = new ArrayList<>();
discover.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
progressDialog = ProgressDialog.show(MainActivity.this, "Press back to cancel", "finding peers", false,
true, new DialogInterface.OnCancelListener() {
#Override
public void onCancel(DialogInterface dialog) {
if(peersList.size()==0)
Toast.makeText(MainActivity.this, "Peer Not Found.", Toast.LENGTH_SHORT).show();
}
});
Runnable progressRunnable = new Runnable() {
#Override
public void run() {
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
}
};
Handler pdCanceller = new Handler();
pdCanceller.postDelayed(progressRunnable, 15000);
wifi.discoverPeers(channel, new WifiP2pManager.ActionListener(){
#Override
public void onSuccess() {
}
#Override
public void onFailure(int reason) {
Toast.makeText(MainActivity.this, "Peer Discovery failed.", Toast.LENGTH_SHORT).show();
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
}
});
}
});
refreshList();
listViewPeer.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if(!isConnected)
connect(position);
else
disconnect();
}
});
send.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
startActivityForResult(intent, CHOOSE_FILE_RESULT_CODE);
}
});
if(!isConnected)
send.setVisibility(View.GONE);
else
send.setVisibility(View.VISIBLE);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
//super.onActivityResult(requestCode, resultCode, data);
Uri uri = data.getData();
serviceIntent = new Intent(this, TransferFile.class);
serviceIntent.setAction(TransferFile.ACTION_SEND_FILE);
serviceIntent.putExtra(TransferFile.EXTRAS_FILE_PATH, uri.toString());
serviceIntent.putExtra(TransferFile.EXTRAS_GROUP_OWNER_ADDRESS, info.groupOwnerAddress.getHostAddress());
serviceIntent.putExtra(TransferFile.EXTRAS_GROUP_OWNER_PORT, 8988);
this.startService(serviceIntent);
Toast.makeText(this, "TransferFile should start.", Toast.LENGTH_SHORT).show();
}
public void connect(int position) {
final WifiP2pDevice device = peersList.get(position);
WifiP2pConfig config = new WifiP2pConfig();
config.deviceAddress = device.deviceAddress;
config.wps.setup = WpsInfo.PBC;
wifi.connect(channel, config, new WifiP2pManager.ActionListener() {
#Override
public void onSuccess() {
}
#Override
public void onFailure(int reason) {
Toast.makeText(MainActivity.this, "Connect failed. Retry.", Toast.LENGTH_SHORT).show();
}
});
}
public void disconnect() {
send.setVisibility(View.GONE);
wifi.removeGroup(channel, new WifiP2pManager.ActionListener() {
#Override
public void onFailure(int reasonCode) {
Toast.makeText(MainActivity.this, "Device disconnecting failed.", Toast.LENGTH_SHORT).show();
}
#Override
public void onSuccess() {
}
});
}
#Override
public void onResume() {
super.onResume();
registerReceiver(receiver, intentFilter);
send.setVisibility(View.GONE);
}
#Override
public void onPause() {
super.onPause();
unregisterReceiver(receiver);
}
#Override
protected void onDestroy() {
super.onStop();
if(isHost)
stopService(serviceIntent);
}
#Override
public void onPeersAvailable(WifiP2pDeviceList peers) {
if (progressDialog != null && progressDialog.isShowing()) {
progressDialog.dismiss();
}
peersList.clear();
peersList.addAll(peers.getDeviceList());
refreshList();
}
public void refreshList(){
peersNameList.clear();
if(peersList.size()!=0){
for(int i=0;i<peersList.size();i++){
peersNameList.add(i, peersList.get(i).deviceName);
}
}
else
send.setVisibility(View.GONE);
final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, peersNameList);
listViewPeer.setAdapter(arrayAdapter);
}
#Override
public void onConnectionInfoAvailable(WifiP2pInfo info) {
this.info = info;
if(!isConnected){
Toast.makeText(MainActivity.this, "Device Connected.", Toast.LENGTH_SHORT).show();
isConnected = true;
if (info.groupFormed && info.isGroupOwner) {
isHost = false;
new FileServerAsyncTask(this).execute();
}
else if(info.groupFormed)
send.setVisibility(View.VISIBLE);
else
Toast.makeText(MainActivity.this, "Nothing matters", Toast.LENGTH_SHORT).show();
}
}
public void reset(){
if(isConnected){
Toast.makeText(MainActivity.this, "Device Disconnected.", Toast.LENGTH_SHORT).show();
isConnected = false;
send.setVisibility(View.GONE);
}
}
public class FileServerAsyncTask extends AsyncTask<Void, Void, String> {
Context context;
FileServerAsyncTask(Context context) {
this.context = context;
}
#Override
protected String doInBackground(Void... params) {
try {
ServerSocket serverSocket = new ServerSocket(8988);
Socket client = serverSocket.accept();
final File f = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + "/"
+ context.getPackageName() + "/wifip2pshared-" + System.currentTimeMillis()
+ ".jpg");
File dirs = new File(f.getParent());
if (!dirs.exists())
dirs.mkdirs();
// Here
// is
// the
// ERROR
f.createNewFile();
InputStream inputstream = client.getInputStream();
copyFile(inputstream, new FileOutputStream(f));
serverSocket.close();
return f.getAbsolutePath();
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
#Override
protected void onPostExecute(String result) {
Toast.makeText(context, "inside post execute." + result, Toast.LENGTH_SHORT).show();
if (result != null) {
Intent intent = new Intent();
intent.setAction(android.content.Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse("file://" + result), "image/*");
context.startActivity(intent);
}
}
#Override
protected void onPreExecute() {
Toast.makeText(context, "Opening a server socket", Toast.LENGTH_SHORT).show();
}
}
public static boolean copyFile(InputStream inputStream, OutputStream out) {
byte buf[] = new byte[1024];
int len;
try {
while ((len = inputStream.read(buf)) != -1) {
out.write(buf, 0, len);
}
out.close();
inputStream.close();
} catch (IOException e) {
return false;
}
return true;
}
}
And this is my FileServerAsycTask class
public class FileServerAsyncTask extends AsyncTask<Void, Void, String> {
Context context;
FileServerAsyncTask(Context context) {
this.context = context;
}
#Override
protected String doInBackground(Void... params) {
try {
ServerSocket serverSocket = new ServerSocket(8988);
Socket client = serverSocket.accept();
final File f = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + "/"
+ context.getPackageName() + "/wifip2pshared-" + System.currentTimeMillis()
+ ".jpg");
File dirs = new File(f.getParent());
if (!dirs.exists())
dirs.mkdirs();
// Here
// is
// the
// ERROR
f.createNewFile();
InputStream inputstream = client.getInputStream();
copyFile(inputstream, new FileOutputStream(f));
serverSocket.close();
return f.getAbsolutePath();
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
#Override
protected void onPostExecute(String result) {
Toast.makeText(context, "inside post execute." + result, Toast.LENGTH_SHORT).show();
if (result != null) {
Intent intent = new Intent();
intent.setAction(android.content.Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse("file://" + result), "image/*");
context.startActivity(intent);
}
}
#Override
protected void onPreExecute() {
Toast.makeText(context, "Opening a server socket", Toast.LENGTH_SHORT).show();
}
}
public static boolean copyFile(InputStream inputStream, OutputStream out) {
byte buf[] = new byte[1024];
int len;
try {
while ((len = inputStream.read(buf)) != -1) {
out.write(buf, 0, len);
}
out.close();
inputStream.close();
} catch (IOException e) {
return false;
}
return true;
}
When on the client side, I try to create a new file using f.createNewFile(), it gives me an error "No such file or directory".
W/System.err: java.io.IOException: open failed: ENOENT (No such file or directory)
W/System.err: at java.io.File.createNewFile(File.java:939)
W/System.err: at com.apposite.wifip2p.MainActivity$FileServerAsyncTask.doInBackground(MainActivity.java:360)
W/System.err: at com.apposite.wifip2p.MainActivity$FileServerAsyncTask.doInBackground(MainActivity.java:310)
W/System.err: at android.os.AsyncTask$2.call(AsyncTask.java:295)
W/System.err: at java.util.concurrent.FutureTask.run(FutureTask.java:237)
W/System.err: at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234)
W/System.err: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
W/System.err: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
W/System.err: at java.lang.Thread.run(Thread.java:818)
W/System.err: Caused by: android.system.ErrnoException: open failed: ENOENT (No such file or directory)
W/System.err: at libcore.io.Posix.open(Native Method)
W/System.err: at libcore.io.BlockGuardOs.open(BlockGuardOs.java:186)
W/System.err: at java.io.File.createNewFile(File.java:932)
W/System.err: ... 8 more
The file's name is...
/storage/emulated/0/com.apposite.wifip2pwifip2pshared-1489935211585.jpg
Please help me how to resolve it!
When creating your Intent to pass the Uri over to the service:
Put in in the data facet of the Intent (setData(), not putExtra()), and
Call addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) on the Intent before calling startService()
Your activity has access to this content; without these changes, your service will not have access to the content.
Also, if your targetSdkVersion is 23 or higher, and you are running on Android 6.0+, you need to handle runtime permissions.

how to record android click event background

I want to record the android click event when I use other apps. For each click, I record its timestamp. So, this app should run background. I use the "getevent" to catch the click event. I am not very familiar with Android operation. My code
has a bug. Its output is not very good, there are many "null"s in the output, and the record is not exactly right.(My app needs root permission)
1.MainActivity.java
package kingofne.seu.edu.ndktest;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private EditText editText = null;
private TextView textView = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText = (EditText) findViewById(R.id.editText);
textView = (TextView) findViewById(R.id.textView);
Button btn_start = (Button) findViewById(R.id.btn_start);
if (btn_start != null) {
btn_start.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setClass(getApplicationContext(), MyService.class);
int param = 1;
if (editText != null) {
param = Integer.valueOf(String.valueOf(editText.getText()));
}
intent.putExtra("param", param);
startService(intent);
Toast.makeText(getApplicationContext(), "start", Toast.LENGTH_SHORT).show();
textView.setText(String.valueOf(System.currentTimeMillis()));
}
});
}
Button btn_stop = (Button) findViewById(R.id.btn_stop);
if (btn_stop != null) {
btn_stop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setClass(getApplicationContext(), MyService.class);
stopService(intent);
Toast.makeText(getApplicationContext(), "stop", Toast.LENGTH_SHORT).show();
}
});
}
}
}
2.MyService.java
package kingofne.seu.edu.ndktest;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.Date;
public class MyService extends Service {
private boolean isRunning = false;
private int param = 1;
private Thread captureThread = null;
private volatile boolean doCapture = false;
public MyService() {
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (isRunning) {
return START_NOT_STICKY;
}
param = intent.getIntExtra("param", 1);
this.captureThread = new Thread(new Producer());
captureThread.setDaemon(true);
this.doCapture = true;
captureThread.start();
isRunning = true;
return START_NOT_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
// stop the thread
this.doCapture = false;
// destroy the thread
this.captureThread = null;
}
private class Producer implements Runnable {
public void run() {
Log.d("ps", "going to run");
Date now = new Date();
SimpleDateFormat sDateFormat = new SimpleDateFormat(
"yyyy-MM-dd-HH-mm-ss");
String str2 = sDateFormat.format(now);
// String location = str2;
//String cmdLine = "getevent -t -l /dev/input/event" + String.valueOf(param) + " > /sdcard/guo" + ".txt";
String cmdLine = "cat /dev/input/event" + String.valueOf(param) + " > /sdcard/guo.txt";
CMDExecute cmd = new CMDExecute();
try {
// cmd.run_su("getevent -t > /sdcard/Yang_"+location+".txt");
cmd.run_su(cmdLine);
} catch (IOException e) {
// TODO Auto-generated catch block
Log.d("ps", "error");
e.printStackTrace();
}
}
};
class CMDExecute {
public synchronized String run(String[] cmd, String workdirectory)
throws IOException {
String result = "";
try {
ProcessBuilder builder = new ProcessBuilder(cmd);
BufferedReader in = null;
// 设置一个路径
if (workdirectory != null) {
builder.directory(new File(workdirectory));
builder.redirectErrorStream(true);
Process process = builder.start();
process.waitFor();
in = new BufferedReader(new InputStreamReader(process
.getInputStream()));
char[] re = new char[1024];
int readNum;
while ((readNum = in.read(re, 0, 1024)) != -1) {
// re[readNum] = '\0';
result = result + new String(re, 0, readNum);
}
}
if (in != null) {
in.close();
}
} catch (Exception ex) {
ex.printStackTrace();
}
return result;
}
public synchronized String run_su(String cmd)
throws IOException {
String result = "";
Process p=null;
try {
p = Runtime.getRuntime().exec("su");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
DataOutputStream os = new DataOutputStream(p.getOutputStream());
BufferedReader is = new BufferedReader(new InputStreamReader(p.getInputStream()));
try {
String istmp;
os.writeBytes(cmd+"\n");
//os.writeBytes("exit\n");
os.flush();
os.writeBytes("exit\n");
os.flush();
p.waitFor();
is.close();
os.close();
p.destroy();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} return result;
}
}
}

Show progress bar with percentage while downloading file using Volley in android

I am using volley to download file using an asynchronous task.I want to show the progress with percentage while the file is being downloaded. But the problem is that the async task is started when the response has come. I can't find any way to track the progress before final response has completely come.
I didn't find any method in JsonRequest that can be used for this.
Below is the onResponse method of request class that extends JsonRequest that i am using.
protected Response<T> parseNetworkResponse(NetworkResponse response) {
if (response.statusCode >= 200 && response.statusCode <= 299) {
// If the status is correct, we return a success but with a null object, because the server didn't return anything
return Response.success(null, HttpHeaderParser.parseCacheHeaders(response));
}
else {
try {
if (downloadFlag) {
DownloadFileAsyncTask downloadFileAsyncTask = new DownloadFileAsyncTask(mContext, fileNameAndExtn,mNotifyManager,mBuilder,mDownloadNotificationUniqueId);
downloadFileAsyncTask.execute(response.data);
} else if (isResponseByteArr) {
return (Response<T>) Response.success(response.data, HttpHeaderParser.parseCacheHeaders(response));
} else {
String json = null;
if (isGzipped(response)) {
json = gzipDecompress(response.data);
} else {
json = new String(response.data,HttpHeaderParser.parseCharset(response.headers));
}
T parsedObject = gson.fromJson(json, clazz);
return Response.success(parsedObject, HttpHeaderParser.parseCacheHeaders(response));
}
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
} catch (JsonSyntaxException e) {
return Response.error(new ParseError(e));
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
DownFileAsyncTask is as follows:
package com.android.webframework.webservice;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Environment;
import android.support.v4.app.NotificationCompat;
import android.webkit.MimeTypeMap;
import android.widget.Toast;
import com.android.applogger.AppLogger;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class DownloadFileAsyncTask extends AsyncTask<byte[], Integer, String> {
private String fileNameAndExtn;
private Context mContext;
private NotificationManager mNotifyManager;
private NotificationCompat.Builder mBuilder;
private int mUniqueId;
public DownloadFileAsyncTask(Context context, String fileNameAndExtn, NotificationManager notifyManager, NotificationCompat.Builder builder, int uniqueId) {
this.fileNameAndExtn = fileNameAndExtn;
this.mContext = context;
this.mNotifyManager = notifyManager;
this.mBuilder = builder;
this.mUniqueId = uniqueId;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
String MEDIA_MOUNTED = "mounted";
#Override
protected String doInBackground(byte[]... bytes) {
File file = null;
int copyCount = 0;
String filePath = "";
String diskState = Environment.getExternalStorageState();
if (diskState.equalsIgnoreCase(MEDIA_MOUNTED)) {
File sd = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
file = new File(sd, fileNameAndExtn);
String fileName = "";
String fileExtn;
String fileNameToSave = fileNameAndExtn;
while (file.exists()) {
copyCount++;
String[] parts = fileNameAndExtn.split("[.]");
if (parts[0] != null)
fileName = parts[0];
fileName += "-" + copyCount;
fileNameToSave = fileName + "." + parts[1];
file = new File(sd, fileNameToSave);
}
fileNameAndExtn = fileNameToSave;
/*if (file.exists()) {
file.delete();
}*/
try {
FileOutputStream fos = new FileOutputStream(file.getPath());
fos.write(bytes[0]);
fos.close();
} catch (IOException e) {
AppLogger.e("file", "Exception in photoCallback", e);
}
AppLogger.e("file Download completed", "***************");
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
intent.setData(Uri.fromFile(file));
mContext.sendBroadcast(intent);
filePath = file.getAbsolutePath();
} else {
Toast.makeText(mContext, "The external disk is not mounted.", Toast.LENGTH_SHORT).show();
}
return (filePath);
}
#Override
protected void onPostExecute(String filePath) {
super.onPostExecute(filePath);
if (fileNameAndExtn != null && !fileNameAndExtn.equalsIgnoreCase("")) {
// Toast.makeText(mContext, "File downloaded in Downloads/" + fileNameAndExtn, Toast.LENGTH_LONG).show();
Toast.makeText(mContext, fileNameAndExtn + " downloaded successfully", Toast.LENGTH_LONG).show();
mBuilder.setProgress(100, 100, false);
Intent intent = getPendingIntent(mContext, filePath);
mBuilder.setContentTitle(fileNameAndExtn)
.setAutoCancel(true)
.setContentText("Download complete");
PendingIntent pendingIntent = null;
if (intent != null) {
pendingIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
}
if (pendingIntent != null) {
mBuilder.setContentIntent(pendingIntent).setProgress(0, 0, false);
}
mNotifyManager.notify(mUniqueId, mBuilder.build());
}
}
#Override
protected void onProgressUpdate(Integer... values) {
mBuilder.setProgress(100, values[0], false);
mNotifyManager.notify(mUniqueId, mBuilder.build());
super.onProgressUpdate(values);
}
public Intent getPendingIntent(Context context, String filePath) {
Intent intent = new Intent(Intent.ACTION_VIEW);
// File file = new File("YOUR_SONG_URI"); // set your audio path
File file = new File(filePath);
intent.setDataAndType(Uri.fromFile(file), getMimeType(filePath));
if (intent.resolveActivityInfo(context.getApplicationContext().
getPackageManager(), 0) != null) {
// context.getApplicationContext().startActivity(intent);
return intent;
} else {
Toast.makeText(context, "File not present or Explorer app not present.",
Toast.LENGTH_LONG).show();
return null;
// if you reach this place, it means there is no any file
// explorer app installed on your device
}
}
public static String getMimeType(String url) {
String filePathWithoutWhiteSpace = url.replaceAll("\\s", "%20");
String type = null;
String extension = MimeTypeMap.getFileExtensionFromUrl(filePathWithoutWhiteSpace);
if (extension != null) {
type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension.toLowerCase());
}
return type;
}
}
not sure you can do this with volley but easy solution for you as you are already using AsyncTask. Here is a link http://www.androidhive.info/2012/04/android-downloading-file-by-showing-progress-bar/ he did the same thing which you are looking.
I solved this problem by creating the notification as soon as the user clicks on download and then the async task notifies after the download is completed but i was not able to show the exact progress while downloading.

Dropbox sync / Google drive, how to upload sqlite database

I am trying to upload a sqlite database file to dropbox. This is my code:
public void uploadDb(){
File public_db_file = null;
try {
public_db_file = writeDbToPublicDirectory();
} catch (IOException e2) {
e2.printStackTrace();
}
DbxFileSystem dbxFs = null;
try {
dbxFs = DbxFileSystem.forAccount(mAccount);
} catch (Unauthorized e1) {
e1.printStackTrace();
}
DbxFile testFile = null;
try {
testFile = dbxFs.create(new DbxPath("database_sync.txt"));
} catch (InvalidPathException e1) {
e1.printStackTrace();
} catch (DbxException e1) {
e1.printStackTrace();
}
try {
testFile.writeFromExistingFile(public_db_file, false);
} catch (IOException e) {
e.printStackTrace();
} finally {
testFile.close();
}
}
EDIT (More code)
This function copies my database from the app private dir to a public dir so that I can upload it:
private File writeDbToPublicDirectory() throws IOException {
// TODO Auto-generated method stub
File sd = Environment.getExternalStorageDirectory();
File backupDB = null;
if (sd.canWrite()) {
String backupDBPath = "copied_database.db";
File currentDB = context.getDatabasePath("private_database");
backupDB = new File(sd, backupDBPath);
if (currentDB.exists()) {
FileChannel src = new FileInputStream(currentDB).getChannel();
FileChannel dst = new FileOutputStream(backupDB).getChannel();
dst.transferFrom(src, 0, src.size());
src.close();
dst.close();
}
}
return backupDB;
}
The problem is that when I check on my device dropbox, the file size is 0 bytes. The file is created on dropbox, but my database data is not. What am I doing wrong? Thank you in advance
EDIT
I have decided that using Google Drive may be a better option, but I can only upload text files by using the sample applications. Is there any good tutorial or resource that I can use to upload a sqlite database file? I am really badly stuck on this. Please help me with either of these, thank you in advance
I was able to backup the database using Google Drive API. I have used the byte array to copy the contents. Following is the Activity code, which creates a new file on Google Drive root folder and copies the sqlite db content. I've added comments wherever required. Let me know whether it helps.
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.drive.Contents;
import com.google.android.gms.drive.Drive;
import com.google.android.gms.drive.DriveFile;
import com.google.android.gms.drive.DriveApi.ContentsResult;
import com.google.android.gms.drive.DriveFolder.DriveFileResult;
import com.google.android.gms.drive.MetadataChangeSet;
import android.app.Activity;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentSender.SendIntentException;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Bundle;
import android.provider.BaseColumns;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.webkit.MimeTypeMap;
public class MainActivity extends Activity implements ConnectionCallbacks, OnConnectionFailedListener {
private static final String TAG = "MainActivity";
private GoogleApiClient api;
private boolean mResolvingError = false;
private DriveFile mfile;
private static final int DIALOG_ERROR_CODE =100;
private static final String DATABASE_NAME = "person.db";
private static final String GOOGLE_DRIVE_FILE_NAME = "sqlite_db_backup";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Create the Drive API instance
api = new GoogleApiClient.Builder(this).addApi(Drive.API).addScope(Drive.SCOPE_FILE).
addConnectionCallbacks(this).addOnConnectionFailedListener(this).build();
}
#Override
public void onStart() {
super.onStart();
if(!mResolvingError) {
api.connect(); // Connect the client to Google Drive
}
}
#Override
public void onStop() {
super.onStop();
api.disconnect(); // Disconnect the client from Google Drive
}
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.v(TAG, "Connection failed");
if(mResolvingError) { // If already in resolution state, just return.
return;
} else if(result.hasResolution()) { // Error can be resolved by starting an intent with user interaction
mResolvingError = true;
try {
result.startResolutionForResult(this, DIALOG_ERROR_CODE);
} catch (SendIntentException e) {
e.printStackTrace();
}
} else { // Error cannot be resolved. Display Error Dialog stating the reason if possible.
ErrorDialogFragment fragment = new ErrorDialogFragment();
Bundle args = new Bundle();
args.putInt("error", result.getErrorCode());
fragment.setArguments(args);
fragment.show(getFragmentManager(), "errordialog");
}
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == DIALOG_ERROR_CODE) {
mResolvingError = false;
if(resultCode == RESULT_OK) { // Error was resolved, now connect to the client if not done so.
if(!api.isConnecting() && !api.isConnected()) {
api.connect();
}
}
}
}
#Override
public void onConnected(Bundle connectionHint) {
Log.v(TAG, "Connected successfully");
/* Connection to Google Drive established. Now request for Contents instance, which can be used to provide file contents.
The callback is registered for the same. */
Drive.DriveApi.newContents(api).setResultCallback(contentsCallback);
}
final private ResultCallback<ContentsResult> contentsCallback = new ResultCallback<ContentsResult>() {
#Override
public void onResult(ContentsResult result) {
if (!result.getStatus().isSuccess()) {
Log.v(TAG, "Error while trying to create new file contents");
return;
}
String mimeType = MimeTypeMap.getSingleton().getExtensionFromMimeType("db");
MetadataChangeSet changeSet = new MetadataChangeSet.Builder()
.setTitle(GOOGLE_DRIVE_FILE_NAME) // Google Drive File name
.setMimeType(mimeType)
.setStarred(true).build();
// create a file on root folder
Drive.DriveApi.getRootFolder(api)
.createFile(api, changeSet, result.getContents())
.setResultCallback(fileCallback);
}
};
final private ResultCallback<DriveFileResult> fileCallback = new ResultCallback<DriveFileResult>() {
#Override
public void onResult(DriveFileResult result) {
if (!result.getStatus().isSuccess()) {
Log.v(TAG, "Error while trying to create the file");
return;
}
mfile = result.getDriveFile();
mfile.openContents(api, DriveFile.MODE_WRITE_ONLY, null).setResultCallback(contentsOpenedCallback);
}
};
final private ResultCallback<ContentsResult> contentsOpenedCallback = new ResultCallback<ContentsResult>() {
#Override
public void onResult(ContentsResult result) {
if (!result.getStatus().isSuccess()) {
Log.v(TAG, "Error opening file");
return;
}
try {
FileInputStream is = new FileInputStream(getDbPath());
BufferedInputStream in = new BufferedInputStream(is);
byte[] buffer = new byte[8 * 1024];
Contents content = result.getContents();
BufferedOutputStream out = new BufferedOutputStream(content.getOutputStream());
int n = 0;
while( ( n = in.read(buffer) ) > 0 ) {
out.write(buffer, 0, n);
}
in.close();
mfile.commitAndCloseContents(api, content).setResultCallback(new ResultCallback<Status>() {
#Override
public void onResult(Status result) {
// Handle the response status
}
});
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
private File getDbPath() {
return this.getDatabasePath(DATABASE_NAME);
}
#Override
public void onConnectionSuspended(int cause) {
// TODO Auto-generated method stub
Log.v(TAG, "Connection suspended");
}
public void onDialogDismissed() {
mResolvingError = false;
}
public static class ErrorDialogFragment extends DialogFragment {
public ErrorDialogFragment() {}
public Dialog onCreateDialog(Bundle savedInstanceState) {
int errorCode = this.getArguments().getInt("error");
return GooglePlayServicesUtil.getErrorDialog(errorCode, this.getActivity(), DIALOG_ERROR_CODE);
}
public void onDismiss(DialogInterface dialog) {
((MainActivity) getActivity()).onDialogDismissed();
}
}
}
I modified #Manish Mulimani's code. I make use of some modules in com.google.android.gms.drive.sample.demo which is available from Google Drive API Website. The modules are BaseDemoActivity, ApiClientAsyncTask and EditContentsActivity. Here are the code.
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.webkit.MimeTypeMap;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.drive.Drive;
import com.google.android.gms.drive.DriveApi;
import com.google.android.gms.drive.DriveContents;
import com.google.android.gms.drive.DriveFile;
import com.google.android.gms.drive.DriveFolder;
import com.google.android.gms.drive.MetadataChangeSet;
import com.google.android.gms.drive.DriveApi.DriveContentsResult;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
public class gDriveActivity extends BaseDemoActivity {
private final static String TAG = "gDriveActivity";
#Override
public void onConnected(Bundle connectionHint) {
super.onConnected(connectionHint);
// create new contents resource.
Drive.DriveApi.newDriveContents(getGoogleApiClient()).setResultCallback(driveContentsCallback);
}
final private ResultCallback<DriveApi.DriveContentsResult> driveContentsCallback =
new ResultCallback<DriveApi.DriveContentsResult>() {
#Override
public void onResult(DriveApi.DriveContentsResult result) {
if (!result.getStatus().isSuccess()) {
//if failure
showMessage("Error while trying to create new file contents");
return;
}
//change the metadata of the file. by setting title, setMimeType.
String mimeType = MimeTypeMap.getSingleton().getExtensionFromMimeType("db");
MetadataChangeSet changeSet = new MetadataChangeSet.Builder()
.setTitle("mydb")
.setMimeType(mimeType)
.build();
Drive.DriveApi.getAppFolder(getGoogleApiClient())
.createFile(getGoogleApiClient(), changeSet, result.getDriveContents()).setResultCallback(fileCallBack);
}
};
final ResultCallback<DriveFolder.DriveFileResult> fileCallBack = new ResultCallback<DriveFolder.DriveFileResult>() {
#Override
public void onResult(DriveFolder.DriveFileResult driveFileResult) {
if (!driveFileResult.getStatus().isSuccess()) {
Log.v(TAG, "Error while trying to create the file");
return;
}
//Initialize mFile to be processed in AsyncTask
DriveFile mfile = driveFileResult.getDriveFile();
new EditContentsAsyncTask(gDriveActivity .this).execute(mfile);
}
};
public class EditContentsAsyncTask extends ApiClientAsyncTask<DriveFile, Void, Boolean> {
public EditContentsAsyncTask(Context context) {
super(context);
}
#Override
protected Boolean doInBackgroundConnected(DriveFile... args) {
DriveFile file = args[0];
try {
DriveContentsResult driveContentsResult = file.open(
getGoogleApiClient(), DriveFile.MODE_WRITE_ONLY, null).await();
if (!driveContentsResult.getStatus().isSuccess()) {
return false;
}
DriveContents driveContents = driveContentsResult.getDriveContents();
//edit the outputStream
DatabaseHandler db = new DatabaseHandler(gDriveActivity .this);
String inFileName = getApplicationContext().getDatabasePath(db.getDatabaseName()).getPath();
FileInputStream is = new FileInputStream(inFileName);
BufferedInputStream in = new BufferedInputStream(is);
byte[] buffer = new byte[8 * 1024];
BufferedOutputStream out = new BufferedOutputStream(driveContents.getOutputStream());
int n = 0;
while ((n = in.read(buffer)) > 0) {
out.write(buffer, 0, n);
}
in.close();
com.google.android.gms.common.api.Status status =
driveContents.commit(getGoogleApiClient(), null).await();
return status.getStatus().isSuccess();
} catch (IOException e) {
Log.e(TAG, "IOException while appending to the output stream", e);
}
return false;
}
#Override
protected void onPostExecute(Boolean result) {
if (!result) {
showMessage("Error while editing contents");
return;
}
showMessage("Successfully edited contents");
}
}
}
I think you could use the Storage API
https://developer.android.com/guide/topics/providers/document-provider.html
A useful tutorial on
http://www.techotopia.com/index.php/An_Android_Storage_Access_Framework_Example

Categories

Resources