So I want to retrieve a string resource from another app. The app is the Android PackageInstaller (most probably a System app) and the String I want to retrieve has multiple language versions (Source Code here > Link). So Package Installer's resource directory looks like this:
I want to retrieve the String permission_warning_template from the values folder (I realize that Android will automatically determine the current language and will fetch me that language's value, but I may be wrong).
These are the 2 methods I wrote (Minimal, Complete, and Verifiable example) and neither works. Is it even possible? How to get it done?
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//First Try
testUseAndroidString();
//Second Try
Resources res = null;
try {
res = getPackageManager().getResourcesForApplication("com.android.packageinstaller");
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
if(null != res) {
int sId = res.getIdentifier("com.android.packageinstaller:string/permission_warning_template", null, null);
if(0 != sId) {
Log.d("TagLet", res.getString(sId));
}
}
}
public void testUseAndroidString() {
Context context = this;
Resources res;
try {
res = context.getPackageManager().getResourcesForApplication("com.android.packageinstaller");
int resourceId = res.getIdentifier("com.android.packageinstaller:string/permission_warning_template", null, null);
if(0 != resourceId) {
CharSequence s = context.getPackageManager().getText("com.android.packageinstaller:string/permission_warning_template", resourceId, null);
Log.d("TagLet", "resource=" + s);
}
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
Log.d("TagLet", "FAIL");
}
}
Thanks.
So you actually almost solved your problem. As you have the resources of another application retreived, you just have to call get{Something} on this res object, and you will get the exact resource.
So I tried this method:
public void testUseAndroidString() {
Context context = this;
Resources res;
try {
res = context.getPackageManager().getResourcesForApplication("com.android.packageinstaller");
int resourceId = res.getIdentifier("com.android.packageinstaller:string/permission_warning_template", null, null);
if(0 != resourceId) {
String s = res.getString(resourceId);
Log.d("TagLet", "resource=" + s);
}
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
}
And got
Allow %1$s to %2$s?
Which I guess is exactly what you're looking for.
Related
I have list of web pages(over 100) with I have to vistit and collect data from.
I decided to save the html from all of them to one file, and then use Jsoup to find the interesting data.
But problem is to I do not know how to run 100 threads, and save the responses into one file, any ideas?
maybe it's not a masterpiece, but it works, and I wanted to make it as simple as possible.
ArrayList<String> links = new ArrayList<>();
Elements myDiv;
private void saveDetails() throws IOException {
if(repeat < links.size()){
repeat++;
textView.setText(String.valueOf(repeat));
saveFile(myDiv.toString());
myDiv = null;
getDetails(links.get(repeat));
}else {
textView.setText("finished");
}
}
private void getDetails(String urlStr) {
final String detailsUrl = urlStr;
new Thread() {
#Override
public void run() {
Message msg = Message.obtain();
try {
Document doc = Jsoup.connect(detailsUrl).get();
myDiv = doc.select(".exhibitor-contact");
} catch (IOException e1) {
e1.printStackTrace();
}
detailsHandler.sendMessage(msg);
}
}.start();
}
private Handler detailsHandler = new Handler() {
public void handleMessage(Message msg) {
super.handleMessage(msg);
try {
saveDetails();
} catch (IOException e) {
e.printStackTrace();
}
}
};
You don't need to save all of them in a file and then process them. You can gather information one by one. It is my suggestion:
arrayList urls = {100 site-url}; //in correct syntax
Document doc = null;
for (String url : urls) {
doc = Jsoup.connect(url).get();
//now proccess doc.toString as you want(in regular expression for example)
//save your desired information
}
I am an android developer, I develop apps for clients.
However, in client devices, some app crash issue usually happened. But it didn't happen in my device.
But I cannot reach my client, so, here is question:~~~~
Is there any plugin or tools that can implement into my android apps, so when the apps is crashed in my client's device, the crash logs will be sent to my email or somewhere I can check it, so I can debug it.
Please advise me, thanks
Go to https://play.google.com/apps/publish/ and publish your app. When users install your app and it crashes it notifies Google, and when you'll login to this control-panel you'll be able to find such reports under the "Reports" tab and then under "CRASHES & ANRS".
Try taking a look at Crashlytics: http://try.crashlytics.com/sdk-android/
I think you should extend Application class, and redefine Exception Handle with stable code (independed of android version).
Code example:
YourApplication.java
public class YourApplication extends Application {
#Override
public void onCreate() {
Thread.setDefaultUncaughtExceptionHandler(ExceptionHandler.inContext(getApplicationContext()));
super.onCreate();
}}
ExceptionHandler.java
final public class ExceptionHandler implements Thread.UncaughtExceptionHandler{
private final DateFormat formatter = new SimpleDateFormat("dd.MM.yy HH:mm");
private final DateFormat fileFormatter = new SimpleDateFormat("dd-MM-yy");
private String versionName = "0";
private int versionCode = 0;
private final String stacktraceDir;
private final Thread.UncaughtExceptionHandler previousHandler;
private ExceptionHandler(Context context, boolean chained) {
PackageManager mPackManager = context.getPackageManager();
PackageInfo mPackInfo;
try {
mPackInfo = mPackManager.getPackageInfo(context.getPackageName(), 0);
versionName = mPackInfo.versionName;
versionCode = mPackInfo.versionCode;
} catch (PackageManager.NameNotFoundException e) {
// ignore
}
if(chained)
previousHandler = Thread.getDefaultUncaughtExceptionHandler();
else
previousHandler = null;
stacktraceDir = String.format("/Android/data/%s/files/", context.getPackageName());
}
static ExceptionHandler inContext(Context context) {
return new ExceptionHandler(context, true);
}
static ExceptionHandler reportOnlyHandler(Context context) {
return new ExceptionHandler(context, false);
}
#Override
public void uncaughtException(Thread thread, Throwable exception) {
final String state = Environment.getExternalStorageState();
final Date dumpDate = new Date(System.currentTimeMillis());
if (Environment.MEDIA_MOUNTED.equals(state)) {
StringBuilder reportBuilder = new StringBuilder();
reportBuilder
.append("\n\n\n")
.append(formatter.format(dumpDate)).append("\n")
.append(String.format("Version: %s (%d)\n", versionName, versionCode))
.append(thread.toString()).append("\n");
processThrowable(exception, reportBuilder);
File sd = Environment.getExternalStorageDirectory();
File stacktrace = new File(
sd.getPath() + stacktraceDir,
String.format(
"stacktrace-%s.txt",
fileFormatter.format(dumpDate)));
File dumpdir = stacktrace.getParentFile();
boolean dirReady = dumpdir.isDirectory() || dumpdir.mkdirs();
if (dirReady) {
FileWriter writer = null;
try {
writer = new FileWriter(stacktrace, true);
writer.write(reportBuilder.toString());
} catch (IOException e) {
// ignore
} finally {
try {
if (writer != null)
writer.close();
} catch (IOException e) {
// ignore
}
}
}
}
if(previousHandler != null)
previousHandler.uncaughtException(thread, exception);
}
private void processThrowable(Throwable exception, StringBuilder builder) {
if(exception == null)
return;
StackTraceElement[] stackTraceElements = exception.getStackTrace();
builder
.append("Exception: ").append(exception.getClass().getName()).append("\n")
.append("Message: ").append(exception.getMessage()).append("\nStacktrace:\n");
for(StackTraceElement element : stackTraceElements) {
builder.append("\t").append(element.toString()).append("\n");
}
processThrowable(exception.getCause(), builder);
}}
If your app will crased, you can find a log with StackTrace at /sdcard/android/data/you.package.name/files/ all log files.
Also you can check new log files at this folder at every app start. If you find new files, you can send this to your email.
I am working on android application. In my app I got the xml data response from server and stored it in a string. Now I need to get each value of that xml and display in a dropdown. How can I do that. Please help me with this. Will be really thankful.
My xml data:
<?xml version="1.0" encoding="utf-8"?>
<root>
<status>first<status>
<description>very good</description>
<Firstnames>
<name>CoderzHeaven</name>
<name>Android</name>
<name>iphone</name>
</Firstnames>
<SecondNames>
<name>Google</name>
<name>Android</name>
</SecondNames>
</root>
I am getting the above mentioned xml data from server. Now I need to display that in listview. How can I get those values using xmlparser. I tried with different examples but it didnt work for me.
You will need to create an extra class and parametrize your adapter with objects of this class, an example data model would look like:
public class DataClass {
private String status, description;
private ArrayList<String> fnames, lnames;
public DataClass() {
fnames = new ArrayList<String>();
lnames = new ArrayList<String>();
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public ArrayList<String> getFnames() {
return fnames;
}
public ArrayList<String> getLnames() {
return lnames;
}
}
As for the XML parser, there are literally tons of examples, you're definitely in advantage if you can use search. Just to give you a staring point, tutorials one, two, three, four.
If you experience problems, post your efforts and the code that didn't work, what have you tried and so on. Then you'll get help, otherwise nobody on SO is going to write code for you. https://stackoverflow.com/help/how-to-ask
Here's how you can do it if the xml is inside of your apps assets folder.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
InputStream input = null;
try {
input = getApplicationContext().getAssets().open("data.xml");
} catch (IOException e) {
e.printStackTrace();
}
DocumentBuilder builder = null;
try {
builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
Document doc = null;
if (builder == null) {
Log.e("TAG", "Builder is empty.");
return;
}
try {
doc = builder.parse(input);
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
if (doc == null) {
Log.e("TAG", "Document is empty.");
return;
}
// Get Firstnames element
Element firstNames = (Element) doc.getElementsByTagName("Firstnames").item(0);
// Get name nodes from Firstnames
NodeList nameNodes = firstNames.getElementsByTagName("name");
// Get count of names inside of Firstnames
int cChildren = nameNodes.getLength();
List<String> names = new ArrayList<String>(cChildren);
for (int i=0; i<cChildren; i++) {
names.add(nameNodes.item(i).getTextContent());
Log.d("TAG","Name: "+names.get(i));
}
// Do same with SecondNames
}
I'm trying to make my program save it's current state on internal memory so i can retrieve it when it loads up next time.
But it seems like i can't get it to work, my app keeps crashing on boot.
private File statoContatori = new File(getFilesDir(), "statoContatori");
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
inizializeCounters();
}
private void inizializeCounters() {
Scanner in = null;
try {
in = new Scanner(statoContatori);
while (in.hasNext())
{
String idContatore = in.next();
String nomeContatore = in.next();
String valore = in.next();
if (idContatore.equals("contatore_1"))
{
initializeContatore(R.id.contatore_1_label, R.id.contatore_1, nomeContatore, valore);
}
else if (idContatore.equals("contatore_2"))
{
initializeContatore(R.id.contatore_2_label, R.id.contatore_2, nomeContatore, valore);
//There are a couple more IFs in here...
}
} catch (FileNotFoundException e) {
creaFileStatoContatori();
}
finally {
in.close();
}
}
private void creaFileStatoContatori() {
PrintWriter out = null;
try {
out = new PrintWriter(statoContatori);
out.println("contatore_1\tcontatore_1\t0");
out.println("contatore_2\tcontatore_2\t0");
out.println("contatore_3\tcontatore_3\t0");
out.println("contatore_4\tcontatore_4\t0");
out.println("contatore_5\tcontatore_5\t0");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
finally {
out.close();
}
inizializeCounters();
}
So basically what i'm trying to do is:
If the file is present -> load the file
If the file is not present -> create the file with standard configs -> load the file
What am i doing wrong?
I got a strange problem, that my app's SharedPreference seems lost some specific keys (not all) when the phone reboot.
Have you ever meet this problem? I used that key to store a serialized object and I did that in my own Application class.
public class Application extends android.app.Application {
static String key = "favs";
SharedPreferences settings;
public Favs favs;
#Override
public void onCreate() {
super.onCreate();
settings = PreferenceManager.getDefaultSharedPreferences(this);
String value = settings.getString(key, "");
if (value != null && value.length() > 0) {
try {
Favs = (Favs ) deSerialize(value.getBytes());
} catch (Exception ex) {
}
}
if(favs == null)
favs = new Favs ();
}
public void storeFavss() {
if (favs == null)
return;
try {
byte[] bytes = serialize(favs );
if(bytes != null)
{
String s = new String(bytes);
settings.edit().putString(key, s);
settings.edit().commit();
}
} catch (Exception ex) {
}
}
After debugging, I will show my own anwser here, hope it can help others.
the code below is bad. it seems the edit() method returns a new object each time.
settings.edit().putString(key, s);
settings.edit().commit();
If you are saving some serialized object bytes in the SharedPreference, Base64 it!
favs = (Favs ) deSerialize(value.getBytes());