Total Commander Forum Index Total Commander
Forum - Public Discussion and Support
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

sdcard2 not writable on Tablet
Goto page Previous  1, 2
 
Post new topic   Reply to topic    Total Commander Forum Index -> Total Commander for Android Printable version
View previous topic :: View next topic  
Author Message
ghisler(Author)
Site Admin
Site Admin


Joined: 04 Feb 2003
Posts: 28349
Location: Switzerland

PostPosted: Mon Sep 10, 2012 7:42 am    Post subject: Reply with quote

Quote:
Copying a folder from internal flash (/mnt/sdcard) does not work.

Thanks for the hint, I will add that.

Quote:
Copying files from the lan (SMB) does not work.

Currently this isn't supported in plugins, but I will try to add it to the next version if possible.

For anyone who wants to do this too, here is a class which you can use to write to the SD-Card. Feel free to use it in your own programs.

Code:
package com.ghisler.android.TotalCommander;

import java.io.OutputStream;

import android.annotation.SuppressLint;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.provider.MediaStore;

public class MediaFileFunctions {
   @SuppressLint({ "NewApi", "NewApi" })
   private static Uri getFileUri(Context context,String fullname) {
      // Note: check outside this class whether the OS version is >= 11
      Uri uri=null;
      Cursor cursor=null;
      ContentResolver contentResolver=null;
      try{
         contentResolver=context.getContentResolver();
         if (contentResolver==null)
            return null;
         uri=MediaStore.Files.getContentUri("external");
         String[] projection=new String[2];
         projection[0]="_id";
         projection[1]="_data";
         String selection="_data = ? ";    // this avoids SQL injection
         String[] selectionParams=new String[1];
         selectionParams[0]=fullname;
         String sortOrder="_id";
         cursor=contentResolver.query(uri, projection, selection, selectionParams, sortOrder);
         if (cursor!=null) {
            try {
               if (cursor.getCount()>0) {  // file present!
                  cursor.moveToFirst();
                  int dataColumn=cursor.getColumnIndex("_data");
                  String s=cursor.getString(dataColumn);
                  if (!s.equals(fullname))
                     return null;
                  int idColumn=cursor.getColumnIndex("_id");
                  long id=cursor.getLong(idColumn);
                  uri=MediaStore.Files.getContentUri("external",id);
               } else {  // file isn't in the media database!
                  ContentValues contentValues=new ContentValues();
                  contentValues.put("_data",fullname);
                  uri=MediaStore.Files.getContentUri("external");
                  uri=contentResolver.insert(uri,contentValues);
               }
            } catch (Throwable e) {
               uri=null;
            }
            cursor.close();
         }
      } catch (Throwable e) {
         uri=null;
      }
      return uri;
   }
   
   public static OutputStream getOutputStreamViaContentProvider(Context context,String fullname) {
      Uri uri=getFileUri(context,fullname);
      if (uri==null)
         return null;
      try {
         ContentResolver resolver=context.getContentResolver();
         return resolver.openOutputStream(uri);
      } catch (Throwable e) {
         return null;
      }
   }
   
   public static boolean deleteViaContentProvider(Context context,String fullname) {
      Uri uri=getFileUri(context,fullname);
      if (uri==null)
         return false;
      try {
         ContentResolver resolver=context.getContentResolver();
         // change type to image, otherwise nothing will be deleted
         ContentValues contentValues=new ContentValues();
         int media_type=1;
         contentValues.put("media_type", media_type);
         resolver.update(uri,contentValues,null,null);
         return resolver.delete(uri,null,null)>0;
      } catch (Throwable e) {
         return false;
      }
   }

   public static boolean mkDirViaContentProvider(Context context,String fullname) {
      String fileName;
      Uri uri;
      ContentResolver resolver;
      try {
         resolver=context.getContentResolver();
         fileName = strcatslash(fullname)+"ghisler_temp.jpg";
         ContentValues contentValues=new ContentValues();
         contentValues.put("_data", fileName);
         uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,contentValues);
      } catch (Throwable e) {
         return false;
      }
      if (uri!=null) {
         try {
            resolver.delete(uri,null,null);
         } catch (Throwable e) {
         }
         return true;
      } else
         return false;
   }

   public static String strcatslash(String dir) {
   if (dir.length()>0 && !dir.endsWith("/"))
      return dir+"/";
   else
      return dir;
    }

}


To create a file on the card, just call:
Code:
boolean ok=true;
OutputStream g = null;
try {
   g = new FileOutputStream(fulltrg);
} catch (Exception e1) {
   ok = false;
}
if (!ok && getOsVersion()>=11 && fulltrg.startsWith("/mnt")) {
g=MediaFileFunctions.getOutputStreamViaContentProvider(this,fulltrg);


It's very important to check the OS version first, otherwise the class will crash your app on the first call! getOsVersion is defined like this:

Code:
   public static int getOsVersion() {
      try {
         java.lang.reflect.Field osField = android.os.Build.VERSION.class.getDeclaredField("SDK_INT");
         osField.setAccessible(true);
         int myBuild = osField.getInt(android.os.Build.VERSION.class);
         return myBuild;
      } catch (Exception e) {
         return 3;
      }
   }


The reason why this works, and the normal File() object doesn't, is the following: We call to the multimedia database for images, music etc. This is part of a different process, which is part of the operating system. Since only operating system processes are allowed to write to the card, this method works. The File() object is part of our own program, therefore it's not allowed to write.
_________________
Author of Total Commander
http://www.ghisler.com
Back to top
View user's profile Send private message Send e-mail Visit poster's website
t_arn
Junior Member
Junior Member


Joined: 28 Dec 2006
Posts: 34

PostPosted: Tue Aug 26, 2014 12:45 am    Post subject: Reply with quote

Hello Christian

Will the MediaFileFunctions class also let me write to my external sdcard on KitKat again? The upgrade of my Samsung S4 to KitKat crippled my external sdcard to a mere media storage while I used it to store all my data before - this *really* made me angry!

Is MediaFileFunctions built into TC 2.04 ?
If yes, then it does not work on my device Sad

I have also tested 2.05b3
There, I can write to /storage/extSdCard/Android/data/com.ghisler.android.TotalCommander/files, but not anywhere else on /storage/extSdCard/

Tom
Back to top
View user's profile Send private message
ghisler(Author)
Site Admin
Site Admin


Joined: 04 Feb 2003
Posts: 28349
Location: Switzerland

PostPosted: Tue Aug 26, 2014 9:02 am    Post subject: Reply with quote

Unfortunately it does not work any more on newer versions of Kitkat, it has all been locked down.
_________________
Author of Total Commander
http://www.ghisler.com
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic    Total Commander Forum Index -> Total Commander for Android All times are GMT - 6 Hours
Goto page Previous  1, 2
Page 2 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Impressum: This site is maintained by Ghisler Software GmbH

Using phpBB © 2001-2005 phpBB Group