I am downloading a file from ftp server. downloading code worked fine, however after download code screen doesn't show anything ,it gets black. Also download function is not returning true value, even the file is being saved in the specified directory.
public class FTPClass{
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_file_player);
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
Intent intent = getIntent();
dirname = intent.getStringExtra("currentDirName");
MyFTPClient mftp = new MyFTPClient();
createPath = mftp.getAppRootPath().concat("/"+ dirname);
mftp.setCurrentDir(createPath);
System.out.println(mftp.ftpChangeDirectory(createPath));
FTPFile[] farr = mftp.ftpListAllFiles();
System.out.println(farr.length);
for(int i = 0; i<farr.length;i++){
System.out.println("SRC: "+createPath+"/"+farr[i].getName());
String src = createPath+"/"+farr[i].getName();
System.out.println("DEST: "+"/data/data/com.example.ftpplayer" + "/app_"+dirname);
String dest ="/data/data/com.example.ftpplayer" + "/app_"+dirname+"/"+farr[i].getName();
System.out.println(mftp.downloadFile(src,dest));
}
}
}
public class CallingIntent extends Activity{
System.out.println("In item click ");
Intent intent = new Intent(getApplicationContext(), FTPClass.class);
String dir = ((TextView) view).getText().toString();
intent.putExtra("currentDirName", dir);
startActivity(intent);
}
public class MyFTPClient{
public boolean downloadFile(String srcPath , String destPath){
try {
FileOutputStream fos = new FileOutputStream(destPath);
System.out.println(mftp.retrieveFile(srcPath, fos)); // retrieve file doesn't return true
fos.flush();
fos.close();
return true;
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}
return false;
}
}
You need to run your code on the background thread, try using an asyncTask.
Related
I read all of the solutions about this problem.Also I know it can be considered as duplicated but it is not.
I see Error: Try Again toast message and I see Update Error log message.
I think at android v26 changed somethings about intent.setDataAndType or I dont know why this is not working.
Also I get the permissions something like this code
ActivityCompat.requestPermissions(Update.this,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
REQUEST_WRITE_STORAGE);
Problem can not be solved. I just want to do download and install apk file.
AndroidManifest.xml (I added write permission)
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Update.java
package com.my.testapp;
public class Update extends AppCompatActivity {
ProgressDialog bar;
private static String TAG = "Update";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new DownloadNewVersion().execute();
}
class DownloadNewVersion extends AsyncTask<String,Integer,Boolean> {
#Override
protected void onPreExecute() {
super.onPreExecute();
bar = new ProgressDialog(Update.this);
bar.setCancelable(false);
bar.setMessage("Downloading...");
bar.setIndeterminate(true);
bar.setCanceledOnTouchOutside(false);
bar.show();
}
protected void onProgressUpdate(Integer... progress) {
super.onProgressUpdate(progress);
bar.setIndeterminate(false);
bar.setMax(100);
bar.setProgress(progress[0]);
String msg = "";
if(progress[0]>99){
msg="Finishing... ";
}else {
msg="Downloading... "+progress[0]+"%";
}
bar.setMessage(msg);
}
#Override
protected void onPostExecute(Boolean result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
bar.dismiss();
if(result){
Toast.makeText(getApplicationContext(),"Update Done",
Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(getApplicationContext(),"Error: Try Again",
Toast.LENGTH_SHORT).show();
}
}
#Override
protected Boolean doInBackground(String... arg0) {
Boolean flag = false;
try {
URL url = new URL("http://mydownloadurl.com/_download/update.apk");
HttpURLConnection c = (HttpURLConnection) url.openConnection();
c.setRequestMethod("GET");
c.setDoOutput(true);
c.connect();
String PATH = Environment.getExternalStorageDirectory()+"/Download/";
File file = new File(PATH);
file.mkdirs();
File outputFile = new File(file,"app-debug.apk");
if(outputFile.exists()){
outputFile.delete();
}
FileOutputStream fos = new FileOutputStream(outputFile);
InputStream is = c.getInputStream();
int total_size = 277962;//size of apk
byte[] buffer = new byte[1024];
int len1 = 0;
int per = 0;
int downloaded=0;
while ((len1 = is.read(buffer)) != -1) {
fos.write(buffer, 0, len1);
downloaded +=len1;
per = (int) (downloaded * 100 / total_size);
publishProgress(per);
}
fos.close();
is.close();
OpenNewVersion(PATH);
flag = true;
} catch (Exception e) {
Log.e(TAG, "Update Error: " + e.getMessage());
flag = false;
}
return flag;
}
}
void OpenNewVersion(String location) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(location + "app-debug.apk")),
"application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
}
Commonsware thanks a lot, I waste my 2-3 hours to do different ways.
Actually I added this code before but the problem was not solved.
I tried again and it worked, it might be lazy solution but it is working.
This url have more info about the problem ,other solutions can be applied,
but it is enough for me.
if(Build.VERSION.SDK_INT>=24){
try{
Method m = StrictMode.class.getMethod("disableDeathOnFileUriExposure");
m.invoke(null);
}catch(Exception e){
e.printStackTrace();
}
}
It is totally fixed thank you very much again.
Application also need this storage permission.
ActivityCompat.requestPermissions(Update.this,new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE
I have an android app that writes files to a directory in internal storage, but it only does that correctly for certain API's. It works fine on my phone which uses Android 5.1 (API 22). And on the Nexus 5 emulator (API 21). However, in most tablets with API >=23 it can't get the directory. It writes the file in a separate activity and puts them in a listView for display in this activity. Whenever this activity loads, it doesn't get any files because the directory 'path' doesn't exist. Yes, I have all the read/write external storage permissions in the manifest. I've included the full code for the activity if anyone really needs to see it, but the part that matters here is only down to the last log tag.
public class ListResults extends Activity {
int data_block = 100;
ArrayList<String> arraylist;
String path_string = Environment.getExternalStorageDirectory().getAbsolutePath()+"/TrafficCounter";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.list_results);
ListView listView1 = (ListView) findViewById(R.id.list);
File path = new File(path_string);
path.mkdirs();
String dir = "" + path;
Log.d("TAG","Path exists: " + path.exists());
Log.d("TAG",String.valueOf(path.mkdirs()));
Log.d("TAG",path.toString());
File f = new File(dir);
String[] fileList = f.list();
Log.d("TAG", Arrays.deepToString(fileList));
//////////////////////////////Rest of Activity (Not Relevant)///////////////////////////////////
arraylist= new ArrayList<String>();
if(fileList!=null){
for(int i=0;i<fileList.length;i++)
{
arraylist.add(fileList[i]);
}}
Collections.sort(arraylist);
ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, arraylist);
listView1.setAdapter(adapter);
listView1.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final String filename = ((TextView) view).getText().toString();
//Creating dialog for choosing what to do with files
final Dialog dialog = new Dialog(ListResults.this);
dialog.setContentView(R.layout.file_options_menu);
dialog.show();
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
TextView nameDisplay = (TextView)dialog.findViewById(R.id.file_name);
nameDisplay.setText(filename);
//Defining all buttons within the dialog
Button viewButton = (Button)dialog.findViewById(R.id.view_button);
Button shareButton = (Button)dialog.findViewById(R.id.share_button);
Button deleteButton = (Button)dialog.findViewById(R.id.delete_button);
Button cancelButton = (Button)dialog.findViewById(R.id.cancel_button);
//View option
viewButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
File path = new File(path_string);
File file = new File(path + "/" + filename);
String[] loadText = Load(file);
String finalString = "";
for (int i = 0; i < loadText.length; i++) {
finalString += loadText[i] + System.getProperty("line.separator");
}
// Launching new Activity on selecting single List Item
Intent i = new Intent(getApplicationContext(), SingleListItem.class);
// sending data to new activity
i.putExtra("product", finalString);
i.putExtra("filename export", filename);
dialog.cancel();
startActivity(i);
finish();
}
});
//Upload option from within the dialog
shareButton.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
File path = new File(path_string);
File file = new File(path + "/" + filename);
Uri uri = Uri.fromFile(file);
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_STREAM, uri);
sendIntent.setType("text/plain");
startActivity(Intent.createChooser(sendIntent,
getResources().getText(R.string.chooser_text)));
dialog.cancel();
}
});
//Delete button function
deleteButton.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
File path = new File(path_string);
File file = new File(path,filename);
file.delete();
Toast.makeText(getApplicationContext(), "File Deleted", Toast.LENGTH_SHORT).show();
dialog.cancel();
Intent intent = getIntent();
finish();
startActivity(intent);
}
});
//Cancel option from dialog
cancelButton.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
dialog.cancel();
}
});
}
});
}
public static String[] Load(File file)
{
FileInputStream fis = null;
try
{
fis = new FileInputStream(file);
}
catch (FileNotFoundException e) {e.printStackTrace();}
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);
String test;
int anzahl=0;
try
{
while ((test=br.readLine()) != null)
{
anzahl++;
}
}
catch (IOException e) {e.printStackTrace();}
try
{
fis.getChannel().position(0);
}
catch (IOException e) {e.printStackTrace();}
String[] array = new String[anzahl];
String line;
int i = 0;
try
{
while((line=br.readLine())!=null)
{
array[i] = line;
i++;
}
}
catch (IOException e) {e.printStackTrace();}
return array;
}
public void onRestart(View view) {
Intent restart = new Intent(this, MainActivity.class);
startActivity(restart);
}
}
I included the log tags I get for each of the following tests. First one is whether or not the directory exists, second line is if mkdirs(); was used, third is the actual address, and fourth is the actual array of files in the directory.
For the Nexus 5 Emulator (API 21, works):
D/TAG: Path exists: true
D/TAG: false
D/TAG: /storage/sdcard/TrafficCounter
D/TAG: [test.txt]
For my actual phone (API 22, works):
D/TAG: Path exists: true
D/TAG: false
D/TAG: /storage/emulated/0/TrafficCounter
D/TAG: [Test.txt]
For Nexus 7 and Nexus S Emulators (API 23, doesn't work):
D/TAG: Path exists: false
D/TAG: false
D/TAG: /storage/emulated/0/TrafficCounter
D/TAG: null
Does anyone know how to properly get the directory for the higher API's? Or am I completely missing something else?
I have an application that saves data to a file called 'sensorLog.txt'. I am not sure where exactly this is stored but I know this is only accessible by the applicationand it is in the internal memory.
I want to be able to write a copy the current file to an external storage when I click on a button "export". I have pasted a small bit of my program, But i am not sure how to copy sensorLog.txt file to the external storage.
public class MainActivity extends Activity {
private static final String DEBUG_TAG = "MainActivity";
private Button buttonStartService;
private Button buttonStopService;
private Button buttonSettings;
private Button buttonExport;
private TextView textStatus;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Context context = getApplicationContext();
setContentView(R.layout.activity_main);
buttonStartService = (Button) findViewById(R.id.button_start_service);
buttonStopService = (Button) findViewById(R.id.button_stop_service);
buttonSettings = (Button) findViewById(R.id.button_settings);
buttonExport = (Button) findViewById(R.id.button_export);
textStatus = (TextView) findViewById(R.id.text_status);
buttonStartService.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
startSensorService();
}
});
buttonStopService.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
stopSensorService();
}
});
//export button listener
buttonExport.setOnClickListener(export_handler);
}
public void startSensorService() {
// Schedule
AlarmManager scheduler = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(getApplicationContext(), SensorService.class);
PendingIntent scheduledIntent = PendingIntent.getService(getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
// 30 seconds
long interval = 30 * 1000;
scheduler.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), interval, scheduledIntent);
Log.d(DEBUG_TAG, "Service started");
}
public void stopSensorService() {
// Cancel
AlarmManager scheduler = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, SensorService.class);
PendingIntent scheduledIntent = PendingIntent.getService(getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
scheduler.cancel(scheduledIntent);
Log.d(DEBUG_TAG, "Service stopped");
}
View.OnClickListener export_handler = new View.OnClickListener() {
public void onClick(View v)
{
// Here is the part I am not sure what to do. I want to copy a file sensorLog.txt that has all my sensor information to sd card
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state))
{
Log.d(DEBUG_TAG, "SD card detected");
stopSensorService();
File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DOCUMENTS),"SensorLog.txt");
// delete file from the internal storage once exported
context.deleteFile("SensorLog.txt");
startSensorService();
}
else
{
Log.d(DEBUG_TAG, "No external storage detected(cannot copy file)");
}
}
};
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
Part where I create sensorLog.txt***(I dont think it is necessary to read for this question but just in case someone needs it)*:
private class SensorServiceLoggerTask extends AsyncTask<SensorFrame, Void, Void> {
#Override
protected Void doInBackground(SensorFrame... frames) {
SensorFrame frame = frames[0];
BufferedWriter bufWr = null;
try {
File file = new File(getApplicationContext().getFilesDir(), "SensorLog.txt");
if (file.exists()) {
// Write to new file
bufWr = new BufferedWriter(new FileWriter(file, true));
} else {
file.createNewFile();
Log.d(DEBUG_TAG, "New log file created");
// Append to existing file
bufWr = new BufferedWriter(new FileWriter(file, false));
// Write header
bufWr.append(sensorHeader.toString());
}
// Write frame
bufWr.append(sensorFrame.toString());
bufWr.flush();
Log.d(DEBUG_TAG, "Added frame to log");
} catch (IOException ex) {
// TODO: useful error handling
} finally {
// Cleanup
if (bufWr != null) {
try {
bufWr.close();
} catch (IOException ex) {
// TODO: useful error handling
}
}
}
return null;
}
}
I also have 2 more queries:
Lets say I want to append some information at the top of the file just before moving it how can I do that?
My aim is to transfer the sensorLog.txt file from internal to external storage when the export button is pressed. delete or empty the internal sensorLog.txt file and then the same thing happens again if i press export again, then I would have to rename my file when I export it right? would there not be a name clash? How do I handle that? could I give a name dynamically?
Thank you.
EDIT: Some corrections
View.OnClickListener export_handler = new View.OnClickListener() {
public void onClick(View v)
{
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state))
{
Log.d(DEBUG_TAG, "SD card detected");
stopSensorService();
Log.d(DEBUG_TAG, "stopSensorService for file transfer");
//make the timestamp the file name
long TS = System.currentTimeMillis();
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(TS);
stringBuilder.append(".txt");
String file_name = stringBuilder.toString();
//file name stored in file_name
File file_ext = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DOCUMENTS),file_name);
// attempt to create this new directory
//read from sensorLog.txt file
try
{
file_ext.createNewFile();
File file = getBaseContext().getFileStreamPath("sensorLog.txt");
if(file.exists())
{
FileInputStream read_file = openFileInput("sensorLog.txt");
//read contents of internal file
InputStreamReader inputStreamReader = new InputStreamReader(read_file);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
StringBuilder sb = new StringBuilder();
sb.append("Timestamp of export to SD"+TS+"/n");
String line;
while ((line = bufferedReader.readLine()) != null) {
sb.append(line);
}
BufferedWriter bufWr = null;
bufWr = new BufferedWriter(new FileWriter(file_ext, false));
// Write header
bufWr.append(sb.toString());
inputStreamReader.close();
bufWr.close();
read_file.close();
//delete sensor file once exported
getApplicationContext().deleteFile("sensorLog.txt");
}
}
catch(Exception e){}
But for some reason my file is not getting stored in the SD card.
Check out the Android documentation. If you can read your sensorLog.txt file, then you can save it in a String and then save the string to a file in the external storage.
How can a file (SQLlite, Text, etc.) be loaded onto the SD card from the Assets folder and only at first run of the application?
Here is the methods I use. Have this as the main activity of your application and use it to start your real application activity.
public class StartUp extends Activity {
/**
* -- Called when the activity is first created.
* ==============================================================
**/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FirstRun();
}
private void FirstRun() {
SharedPreferences settings = this.getSharedPreferences("YourAppName", 0);
boolean firstrun = settings.getBoolean("firstrun", true);
if (firstrun) { // Checks to see if we've ran the application b4
SharedPreferences.Editor e = settings.edit();
e.putBoolean("firstrun", false);
e.commit();
// If not, run these methods:
SetDirectory();
Intent home = new Intent(StartUp.this, YourMainActivity.class);
startActivity(home);
} else { // Otherwise start the application here:
Intent home = new Intent(StartUp.this, YourMainActivity.class);
startActivity(home);
}
}
/**
* -- Check to see if the sdCard is mounted and create a directory w/in it
* ========================================================================
**/
private void SetDirectory() {
if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) {
extStorageDirectory = Environment.getExternalStorageDirectory().toString();
File txtDirectory = new File(extStorageDirectory + "/yourAppName/txtDirectory/");//Example name for txt files
// Create
// a
// File
// object
// for
// the
// parent
// directory
txtDirectory.mkdirs();// Have the object build the directory
// structure, if needed.
CopyAssets(); // Then run the method to copy the file.
} else if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED_READ_ONLY)) {
AlertsAndDialogs.sdCardMissing(this);//Or use your own method ie: Toast
}
}
/**
* -- Copy the file from the assets folder to the sdCard
* ===========================================================
**/
private void CopyAssets() {
AssetManager assetManager = getAssets();
String[] files = null;
try {
files = assetManager.list("");
} catch (IOException e) {
Log.e("tag", e.getMessage());
}
for (int i = 0; i < files.length; i++) {
InputStream in = null;
OutputStream out = null;
try {
in = assetManager.open(files[i]);
out = new FileOutputStream(extStorageDirectory + "/yourAppName/txt/" + files[i]);
copyFile(in, out);
in.close();
in = null;
out.flush();
out.close();
out = null;
} catch (Exception e) {
Log.e("tag", e.getMessage());
}
}
}
private void copyFile(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
}
when user click on url link i want to install apk file from server.
please guide me how to do i searched on net i am not getting corresponding info
Thanks in advance
Aswan
Installing non-Market Apps on Android Phone
This is the code i use, it is not for a webview but you could easily override url loading and apply this code anyways..
The intent at the bottom is the answer to your question.
/**
* Main
* When started, will download latest version of AN APPLICATIONand launch an install
* Is just a dialog
*
* REQUIRES SDCARD
* #author Dag
*
*/
public class Main extends Activity {
ProgressDialog dlDialog;
String path = Environment.getExternalStorageDirectory()+ "/"; // Path to where you want to save the file
String inet = "http://www.google.com/test.apk"; // Internet path to the file
String cachedir = "";
String filename = "TMC.apk";
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView webview = new TextView(this);
setContentView(webview);
File getcache = this.getCacheDir();
cachedir = getcache.getAbsolutePath();
dlDialog = new ProgressDialog(Main.this);
dlDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
dlDialog.setTitle("Downloadin");
dlDialog.setMessage("Connecting");
dlDialog.show();
new Thread(new Runnable() {
public void run() {
String filePath = path;
InputStream is = null;
OutputStream os = null;
URLConnection URLConn = null;
try {
URL fileUrl;
byte[] buf;
int ByteRead = 0;
int ByteWritten = 0;
fileUrl = new URL(inet);
URLConn = fileUrl.openConnection();
is = URLConn.getInputStream();
String fileName = inet.substring(inet.lastIndexOf("/") + 1);
File f = new File(filePath);
f.mkdirs();
String abs = filePath + fileName;
f = new File(abs);
os = new BufferedOutputStream(new FileOutputStream(abs));
buf = new byte[1024];
/*
* This loop reads the bytes and updates a progressdialog
*/
while ((ByteRead = is.read(buf)) != -1) {
os.write(buf, 0, ByteRead);
ByteWritten += ByteRead;
final int tmpWritten = ByteWritten;
runOnUiThread(new Runnable() {
public void run() {
dlDialog.setMessage(""+tmpWritten+" Bytes");
}
});
}
runOnUiThread(new Runnable() {
public void run() {
dlDialog.setTitle("Startar");
}
});
is.close();
os.flush();
os.close();
Thread.sleep(200);
dlDialog.dismiss();
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(abs)),
"application/vnd.android.package-archive");
startActivity(intent);
finish();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
}
You cannot force an APK to be installed...
If it were so anybody could hide viruses or spyware on some servers and when the user clicks a link it automatically gets installed...
Simply put the apk-file you want to install on your server and let the hyperlink point to it... just like to a zip-archive, movie or other executable file.
The browser simply will download the apk and install it (if the user wants so). The user of course needs to activate non-market apps in his settings... (as described in the link above)
I hope this helps you...