How to get media files and their details with Dropbox API v2 for Android(Java)? I have gone through the documentation for the FileMetadata , but I couldn't find the methods to get file details like file type(e.g. music, video, photo, text, ...) , file's URL and thumbnail.
this is my folders and files list Asyntask:
//login
DbxClientV2 client = DropboxClient.getClient(accessToken);
// Get files and folder metadata from root directory
String path = "";
TreeMap<String, Metadata> children = new TreeMap<>();
try {
try {
result = client.files().listFolder(path);
arrayList = new ArrayList<>();
//arrayList.add("/");
while (true) {
int i = 0;
for (Metadata md : result.getEntries()) {
if (md instanceof DeletedMetadata) {
children.remove(md.getPathLower());
} else {
String fileOrFolder = md.getPathLower();
children.put(fileOrFolder, md);
//if (!fileOrFolder.contains("."))//is a file
arrayList.add(fileOrFolder);
if (md instanceof FileMetadata) {
FileMetadata file = (FileMetadata) md;
//I need something like file.mineType, file.url, file.thumbnail
file.getParentSharedFolderId();
file.getName();
file.getPathLower();
file.getPathDisplay();
file.getClientModified();
file.getServerModified();
file.getSize();//in bytes
MediaInfo mInfo = file.getMediaInfo();//Additional information if the file is a photo or video, null if not present
MediaInfo.Tag tag;
if (mInfo != null) {
tag = mInfo.tag();}
}
}
i++;
}
if (!result.getHasMore()) break;
try {
result = client.files().listFolderContinue(result.getCursor());//what is this for ?
} catch (ListFolderContinueErrorException ex) {
ex.printStackTrace();
}
}
} catch (ListFolderErrorException ex) {
ex.printStackTrace();
}
} catch (DbxException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return result;
If you want media information, you should use listFolderBuilder to get a ListFolderBuilder object. You can use call .withIncludeMediaInfo(true) to set the parameter for media information, and then .start() to make the API call. The results will then have the media information set, where available.
Dropbox API v2 doesn't offer mime types, but you can keep your own file extension to mime type mapping as desired.
To get an existing link for a file, use listSharedLinks. To create a new one, use createSharedLinkWithSettings.
To get a thumbnail for a file, use getThumbnail.
I placed 10 images in drawable folder and I created a custom class which instances are holding an id Integer that should refer it to a image from draw folder. Now I wonder how to set those id-s at once, not one by one. Instead:
object[0].setImage(R.drawable.image1);
object[1].setImage(R.drawable.image2);
I want to do this with loop, but how?
Drawable ids as known are generated within static classes of final class R. So just use reflection to read the values of these static attributes. If you want to get the Int ids then use this code:
for(Field f : R.drawable.class.getDeclaredFields()){
if(f.getType() == int.class){
try {
int id = f.getInt(null);
// read the image from the id
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e){
e.printStackTrace();
}
}
}
Or if you want to search directly by images' names, you might be interested of the name attribute of fields like :
for(Field f : R.drawable.class.getDeclaredFields()){
if(f.getType() == int.class){
try {
String name = f.getName();
// rest of the code handling file loading
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
}
}
Doesn't work as far as I think.
There is code to get a drawable by its name. For example: "image"+myNumber"
Maybe: how to access the drawable resources by name in android
Be aware that the size of the view's list should match with the one that holds the ids:
public class HolderIDs {
public List<Integer> _ids;
public HolderIDs() {
_ids = new ArrayList<Integer>(Arrays.asList(R.drawable.one, R.drawable.two, R.ldrawable.three, R.drawable.four));
}
public List<Integer> getIDs() {
return _ids;
}
}
//Usage
List<ImageView> views = getYourViews();
List<Integer> ids = new HolderIDs().getIDs();
for (int i = 0; i < ids.size(); i++) {
View view = views.get(i);
if (view == null) return;
int id = ids.get(i);
view.setBackgroundResource(id);
}
You can create an integer array for the resources:
int resources = [ R.drawable.image1, R.drawable.image2, ...]
And use a bucle to set the resources into your object array.
I would need to List all the values in strings.xml (for a given locale),
basically get a dynamic list of all the strings in an application.
My purpose here is to list all strings of all apps inside my (duely rooted) phone in order to speed up translation work.
I have no problem accessing the AssetManager of other apps :
-To get the list of all apps I use :
List<PackageInfo> packs = getPackageManager().getInstalledPackages(0);
-To access the package manager I use :
PackageManager manager = getPackageManager();
Resources mApk1Resources = manager.getResourcesForApplication(pname);
AssetManager a = mApk1Resources.getAssets();
But I am not quite sure where to go from here.
Obviously this is not for production purpose, just for helping my customer's translation team (you know Chinese OEMs...), so jackhammer-dirty solutions are welcome :-P (reflection, dynamic foreign context, live dex loading, dynamite etc...)
Thanks !
Edit 1 : I already know B.A.R.T it doesn't suit my need I need to do it on a live phone (not a zipped ROM) like a "live translation checker app". In particular, I don't have immediate access to the app's source codes, because I have to check a large number of phones, some being few years old. I can spend the time to root all of them if needed, but not much more.
Edit 2 : I really need something that runs on a live phone without the need of a PC. I can't modify the source code of individual apps and I can't decompile the ROM or use external tools like B.A.R.T I need an all-Java solution.
I can see that: usually the string for application label will get the first id in the resource strings. (not found an official document on this yet)
So the plan is: get the id of the label of an app, increase the id each time to get the next resource string until we get the Resources.NotFoundException
try {
List<ApplicationInfo> apps = getPackageManager()
.getInstalledApplications(0);
for (ApplicationInfo appInfo : apps) {
Resources mApk1Resources = getPackageManager()
.getResourcesForApplication(appInfo.packageName);
int id = appInfo.labelRes;
try {
Log.e("Test", "*******************************************");
Log.e("Test", apps.get(0).packageName);
while (true) {
Log.e("Test",
"String resource: "
+ mApk1Resources.getString(id));
id++;
}
} catch (Resources.NotFoundException e) {
// Handle exception
}
}
} catch (NameNotFoundException e) {
// Handle exception
}
Seeing you said you accept "jackhammer-dirty solutions", give this a try:
In your Strings.xml, surround all your String values with a <string-array> tag, and all string tags inside change to item tags, like so (used simple find-and-replace to replace the tag names):
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello World!</string>
<string name="app_name">YourAppNAme</string>
<string-array name="yourTitle">
<item>item1</item> //used to be <string name"blabla">....
<item>item2</item>
<item>item3</item>
</string-array>
</resources>
In your xml Layout file, where you have your ListView, put:
<ListView
android:id=”#+id/yourListView”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:entries="#array/yourTitle"
/>
Now, your Activity where you have your List, just call the ListView which should already be populated with the items from the Strings.xml
Don't forget to revert the changes in Strings.xml once you are done (and backup is always a good idea)!
Read more Here
Hope this helps!
Since you've rooted the phone and have access to every APK in the phone, how about just decompile them and get to the strings that way, see tutorial here: http://www.miui-au.com/add-ons/apktool/
Ok, I guess I found it. Reflection did the trick !
Root was not even needed. Crazy to know that any apps on your phone can see all the other's ressources...
public void listAllStrings(){
List<PackageInfo> packs = getPackageManager().getInstalledPackages(0);
for(int i=0;i<packs.size();i++) {
PackageInfo p = packs.get(i);
String pname = p.packageName;
Resources packageResources=null;
Context packageContext=null;
try
{
packageResources = MainActivity.this.getPackageManager().getResourcesForApplication(pname);
packageContext = MainActivity.this.createPackageContext(pname, Context.CONTEXT_INCLUDE_CODE + Context.CONTEXT_IGNORE_SECURITY);
}
catch(NameNotFoundException excep)
{
// the package does not exist. move on to see if another exists.
Log.e(pname, "Package not found!");
}
Class<?> stringClass=null;
try
{
// using reflection to get the string class inside the R class of the package
stringClass = packageContext.getClassLoader().loadClass(pname + ".R$string");
}
catch (ClassNotFoundException excep1)
{
// Less chances that class won't be there.
Log.e(pname, "R.string not found!");
}
if(stringClass!=null){
//For every fields of the string class
for( Field stringID : stringClass.getFields() )
{
try
{
//We get the id
int id = stringID.getInt(stringClass);
//We get the string value itself
String xmlResourceLayout = packageResources.getString(id);
Log.v(pname, xmlResourceLayout);
}
catch (Exception excep)
{
Log.e(pname, "Can't access : "+stringID.getName());
continue;
}
}
}
}
}
Hope this can help others :-)
Edit : For some Apks, the R class is not at the root of the package, so I had to write a find-R function
String findR(Context packageContext){
try {
//First case, the R class is easy to find !
packageContext.getClassLoader().loadClass(packageContext.getPackageName() + ".R");
return packageContext.getPackageName() + ".R";
} catch (Exception e) {
//Second case, it is not at the root of the package, we will list all classes...
Log.v(packageContext.getPackageName(),"R not found... Continue searching !");
try {
final PackageManager pm = getApplicationContext().getPackageManager();
ApplicationInfo ai = pm.getApplicationInfo(packageContext.getPackageName(), 0);
DexFile dx = DexFile.loadDex(ai.sourceDir, File.createTempFile("opt", "dex",
getCacheDir()).getPath(), 0);
String pathToR=null;
// Search inside each and every class in the dex file
for(Enumeration<String> classNames = dx.entries(); classNames.hasMoreElements();) {
String className = classNames.nextElement();
//for every single class, we will see if one of the fields is called app_name
//Log.v(className, "Class detail : "+className);
if(className.contains("R$string")) pathToR=className;
}
if(pathToR==null) throw new ClassNotFoundException();
pathToR=pathToR.replaceAll("$string", "");
Log.v(packageContext.getPackageName(), "R FOUND ! "+packageContext.getPackageName());
return pathToR;
} catch (Exception exc) {
Log.e(packageContext.getPackageName(), "ERROR ! R NOT FOUND ...");
return null;
}
}
}
But it still doesn't work in every case. So I ended hijacking the apktools library so it could run live on a phone... (I used the jar from 1.5.2 http://code.google.com/p/android-apktool/downloads/detail?name=apktool1.5.2.tar.bz2&can=2&q=) Here is my hijacked class :
public class Decoder {
public void decode(ResTable resTable, ExtFile apkFile, File outDir)
throws AndrolibException {
Duo<ResFileDecoder, AXmlResourceParser> duo = getResFileDecoder();
ResFileDecoder fileDecoder = duo.m1;
ResAttrDecoder attrDecoder = duo.m2.getAttrDecoder();
attrDecoder.setCurrentPackage(resTable.listMainPackages().iterator()
.next());
Directory inApk, in = null, out;
try {
inApk = apkFile.getDirectory();
out = new FileDirectory(outDir);
Log.v(MainActivity.SMALL_TAG,"Decoding AndroidManifest.xml with resources...");
fileDecoder.decodeManifest(inApk, "AndroidManifest.xml", out,
"AndroidManifest.xml");
// fix package if needed
adjust_package_manifest(resTable, outDir.getAbsolutePath()
+ "/AndroidManifest.xml");
if (inApk.containsDir("res")) {
in = inApk.getDir("res");
}
out = out.createDir("res");
} catch (DirectoryException ex) {
throw new AndrolibException(ex);
}
ExtMXSerializer xmlSerializer = getResXmlSerializer();
for (ResPackage pkg : resTable.listMainPackages()) {
attrDecoder.setCurrentPackage(pkg);
//Log.v(MainActivity.SMALL_TAG,"Decoding file-resources...");
//for (ResResource res : pkg.listFiles()) {
// fileDecoder.decode(res, in, out);
//}
Log.v(MainActivity.SMALL_TAG,"Decoding values */* XMLs...");
for (ResValuesFile valuesFile : pkg.listValuesFiles()) {
generateValuesFile(valuesFile, out, xmlSerializer);
}
generatePublicXml(pkg, out, xmlSerializer);
Log.v(MainActivity.SMALL_TAG,"Done.");
}
AndrolibException decodeError = duo.m2.getFirstError();
if (decodeError != null) {
throw decodeError;
}
}
public Duo<ResFileDecoder, AXmlResourceParser> getResFileDecoder() {
ResStreamDecoderContainer decoders = new ResStreamDecoderContainer();
decoders.setDecoder("raw", new ResRawStreamDecoder());
//decoders.setDecoder("9patch", new Res9patchStreamDecoder());
//TODO THIS DECODER CREATES ALL PROBLEMS !
AXmlResourceParser axmlParser = new AXmlResourceParser();
axmlParser.setAttrDecoder(new ResAttrDecoder());
decoders.setDecoder("xml", new XmlPullStreamDecoder(axmlParser,
getResXmlSerializer()));
return new Duo<ResFileDecoder, AXmlResourceParser>(new ResFileDecoder(
decoders), axmlParser);
}
public static final String PROPERTY_SERIALIZER_INDENTATION = "http://xmlpull.org/v1/doc/properties.html#serializer-indentation";
public static final String PROPERTY_SERIALIZER_LINE_SEPARATOR = "http://xmlpull.org/v1/doc/properties.html#serializer-line-separator";
public static final String PROPERTY_DEFAULT_ENCODING = "DEFAULT_ENCODING";
public ExtMXSerializer getResXmlSerializer() {
ExtMXSerializer serial = new ExtMXSerializer();
serial.setProperty(PROPERTY_SERIALIZER_INDENTATION,
" ");
serial.setProperty(PROPERTY_SERIALIZER_LINE_SEPARATOR,
System.getProperty("line.separator"));
serial.setProperty(PROPERTY_DEFAULT_ENCODING, "utf-8");
serial.setDisabledAttrEscape(true);
return serial;
}
public void adjust_package_manifest(ResTable resTable, String filePath)
throws AndrolibException {
// check if packages different, and that package is not equal to
// "android"
Map<String, String> packageInfo = resTable.getPackageInfo();
if ((packageInfo.get("cur_package").equalsIgnoreCase(
packageInfo.get("orig_package")) || ("android"
.equalsIgnoreCase(packageInfo.get("cur_package")) || ("com.htc"
.equalsIgnoreCase(packageInfo.get("cur_package")))))) {
Log.v(MainActivity.SMALL_TAG,"Regular manifest package...");
} else {
try {
Log.v(MainActivity.SMALL_TAG,"Renamed manifest package found! Fixing...");
DocumentBuilderFactory docFactory = DocumentBuilderFactory
.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.parse(filePath.toString());
// Get the manifest line
Node manifest = doc.getFirstChild();
// update package attribute
NamedNodeMap attr = manifest.getAttributes();
Node nodeAttr = attr.getNamedItem("package");
mPackageRenamed = nodeAttr.getNodeValue();
nodeAttr.setNodeValue(packageInfo.get("cur_package"));
// re-save manifest.
TransformerFactory transformerFactory = TransformerFactory
.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File(filePath));
transformer.transform(source, result);
} catch (ParserConfigurationException ex) {
throw new AndrolibException(ex);
} catch (TransformerException ex) {
throw new AndrolibException(ex);
} catch (IOException ex) {
throw new AndrolibException(ex);
} catch (SAXException ex) {
throw new AndrolibException(ex);
}
}
}
private void generatePublicXml(ResPackage pkg, Directory out,
XmlSerializer serial) throws AndrolibException {
try {
OutputStream outStream = out.getFileOutput("values/public.xml");
serial.setOutput(outStream, null);
serial.startDocument(null, null);
serial.startTag(null, "resources");
for (ResResSpec spec : pkg.listResSpecs()) {
serial.startTag(null, "public");
serial.attribute(null, "type", spec.getType().getName());
serial.attribute(null, "name", spec.getName());
serial.attribute(null, "id",
String.format("0x%08x", spec.getId().id));
serial.endTag(null, "public");
}
serial.endTag(null, "resources");
serial.endDocument();
serial.flush();
outStream.close();
} catch (IOException ex) {
throw new AndrolibException("Could not generate public.xml file",
ex);
} catch (DirectoryException ex) {
throw new AndrolibException("Could not generate public.xml file",
ex);
}
}
private void generateValuesFile(ResValuesFile valuesFile, Directory out,
ExtXmlSerializer serial) throws AndrolibException {
try {
OutputStream outStream = out.getFileOutput(valuesFile.getPath());
serial.setOutput((outStream), null);
serial.startDocument(null, null);
serial.startTag(null, "resources");
for (ResResource res : valuesFile.listResources()) {
if (valuesFile.isSynthesized(res)) {
continue;
}
((ResValuesXmlSerializable) res.getValue())
.serializeToResValuesXml(serial, res);
}
serial.endTag(null, "resources");
serial.newLine();
serial.endDocument();
serial.flush();
outStream.close();
} catch (IOException ex) {
throw new AndrolibException("Could not generate: "
+ valuesFile.getPath(), ex);
} catch (DirectoryException ex) {
throw new AndrolibException("Could not generate: "
+ valuesFile.getPath(), ex);
}
}
private String mPackageRenamed = null;
}
and here's how I use it :
String pname = p.packageName;
Context packageContext = MainActivity.this.createPackageContext(pname, Context.CONTEXT_INCLUDE_CODE + Context.CONTEXT_IGNORE_SECURITY);
ApplicationInfo ai = packageContext.getApplicationInfo();
Log.v(TAG,"Analysing : "+pname+" "+ai.sourceDir);
if(new File(destination.getAbsolutePath()+"/"+pname+".strings.xml").exists()){
Log.v(TAG,"Already translated...");
continue;
}
ApkDecoder decoder = new ApkDecoder();
decoder.setApkFile(new File(ai.sourceDir));
File directory = new File(Environment.getExternalStorageDirectory()+File.separator+"tempApk");
directory.mkdirs();
DeleteRecursive(directory);
directory.mkdirs();
decoder.setOutDir(directory);
decoder.setForceDelete(true);
File frmwrk = new File(Environment.getExternalStorageDirectory()+File.separator+"framework");
frmwrk.mkdirs();
decoder.setFrameworkDir(Environment.getExternalStorageDirectory()+File.separator+"framework");
decoder.setDecodeSources((short)0x0000);
decoder.setKeepBrokenResources(true);
try{
//decoder.decode();
new Decoder().decode(decoder.getResTable(), new ExtFile(new File(ai.sourceDir)), directory);
} catch (Throwable e) {
e.printStackTrace();
}
Lots of headaches for few Strings ;-)
Hello,
I am trying to read a file with a Scanner so I can use the input of the strings to construct other objects. However my scanner is always throwing a NullPointerException when trying to create it. I have a pig.txt text file in the res/raw folder but my scanner can not seem to access it. I do not know what I am doing wrong. I have comment out other code of the method but still get an exception.
public void loadAchievements() {
try {
Scanner s = new Scanner(getResources().openRawResource(R.raw.pig));
/**
* s = s.useDelimiter("."); Scanner StringScanner; StringScanner =
* new Scanner(s.next()); StringScanner =
* StringScanner.useDelimiter(":"); String keep =
* StringScanner.next(); String StringKeeper = StringScanner.next();
* this.achievementBoard.add(new Achievement_Item(keep,
* StringKeeper)); StringScanner.close(); s.close();
**/
} catch (NullPointerException e) {
e.printStackTrace();
System.out.println("NULLPOINTER");
}
}
I had this problem today, and I resolved somehow.
I know that old question, but I would share it if others have stuck.
public class Question {
private int numberOfQuestion;
private String[] myquestion;
public Question(InputStream file_name) {
Scanner scanner = null;
try {
scanner = new Scanner(file_name);
} catch (Exception e) {
Log.d("Question", "Scanner :" + e);
System.exit(1);
}
this.numberOfQuestion = scanner.nextInt();
scanner.nextLine();
myquestion = new String[numberOfQuestion];
for (int i = 0; i < numberOfQuestion; ++i) {
myquestion[i] = scanner.nextLine();
}
scanner.close();
}
---------------------------------------------------------
call:
try {
MyScanner myScanner = new MyScanner(getResources().openRawResource( R.raw.input_question));
} catch (Exception e) {
Log.d("Error", "input_question.txt");
}
openRawResource() method can only be used to open drawable, sound, and raw resources; it will fail on string and color resources. Since your pig.txt is a text file that contains a String, openRawResource() won't be able to open a new stream therefore your stream is null.
So All I'm trying to do is create a dynamic expandableListView Currently It works if I just do the groupViews. The problem comes in when I have to populate the children of those groupViews.. I don't know if I'm doing something wrong, or if theres another better way to do it. If anyone knows please let me know. I'm open to anything.
Currently I'm pulling my data off a server and the error I'm getting is java null pointer exception. So I'm thinking it might have something to do with how big I specified my array sizes?
private static String[][] children = new String[7][4];
private static String[] groups = new String[7];
Here is the rest of the code when I try to populate the View.
public void getData(){
try {
int tempGroupCount = 0;
URL food_url = new URL (Constants.SERVER_DINING);
BufferedReader my_buffer = new BufferedReader(new InputStreamReader(food_url.openStream()));
temp = my_buffer.readLine();
// prime read
while (temp != null ){
childrenCount = 0;
// check to see if readline equals Location
//Log.w("HERasdfsafdsafdsafE", temp);
// start a new location
if (temp.equalsIgnoreCase("Location"))
{
temp = my_buffer.readLine();
groups[tempGroupCount] = temp;
tempGroupCount++;
Log.w("HERE IS TEMP", temp);
}
temp = my_buffer.readLine();
while (temp.equalsIgnoreCase("Location") == false){
Log.w("ONMG HEHREHRHERHER", temp);
children[groupCount][childrenCount] = "IAJHSDSAD";
childrenCount++;
temp = my_buffer.readLine();
}
groupCount++;
}
my_buffer.close();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
Log.e("IO EXCEPTION", "Exception occured in MyExpandableListAdapter:" + e.toString());
}
}
to me it looks like an error in the loop - as you are reading another line without checking is it null
your while loop should look something like this methinks:
// prime read
while (temp != null ){
int childrenCount = 0;
// check to see if readline equals Location
// start a new location
//Log.w("HERasdfsafdsafdsafE", temp);
if (temp.equalsIgnoreCase("Location"))
{
temp = my_buffer.readLine();
groups[tempGroupCount] = temp;
tempGroupCount++;
Log.w("HERE IS TEMP", temp);
}
//>>remove following line as that one isn't checked and
//>>you are loosing on a line that is potentialy a child
//temp = my_buffer.readLine();
//>>check do you have first item to add subitems
else if (tempGroupCount>0){
while (temp.equalsIgnoreCase("Location") == false){
Log.w("ONMG HEHREHRHERHER", temp);
children[tempGroupCount-1][childrenCount] = "IAJHSDSAD";
childrenCount++;
temp = my_buffer.readLine();
}
//>>next counter is probably not need but can't see if you're using it somewhere else
//groupCount++;
}
I would first replace strings array to some 2d collection for example arraylist2d ( you can google it ) so you could easally add and remove data from list. If you created adapter that extends BaseExpandableListAdapter everything should be handled without any problems.
About NULLPointer, could you paste stacktrace or more info on which line it occurs ?