Im trying to figure out an easier (more automated way) to see all the version numbers of the apk's (both user installed and preinstalled) that are currently installed on an Android device.
currently I have been going about it like this:
a. The version is in the apk
b. The apk is typically in /system/app
c. The package name to apk name can be found in /data/system/packages.xml
d. The tricky part is that the application NAME is usually in a string resource in the apk file – like strings.xml (default name)
e. This can also be done from within the android SDK using the PackageManager family of API’s
This is extremely time consuming and Im doing this for many, many, many devices. Im just thinking that there has to be an easier way then how Im going about it.
Thanks for the help, as always, its very appreciated.
The only one of your approaches that is valid is:
This can also be done from within the android SDK using the PackageManager family of API’s
The rest... I have no idea why you think it would even work, let alone do so reliably. What makes you think that people will be using string resources for these, considering that versionCode in particular never has to be translated?
This is extremely time consuming
The code to call PackageManager, iterate over the installed applications, and retrieve the version information should take a handful of milliseconds.
I did it, whoooo!!! ..... I am posting this code to anyone else that need to find the packagenames and version names of everything on the device.
import java.util.List;
import android.app.Activity;
import android.content.pm.PackageInfo;
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.widget.TextView;
public class main extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String bldr = new String();
List<PackageInfo> packs = getPackageManager().getInstalledPackages(0);
bldr = "Total packages --> " + packs.size() + "\n";
for(int i=0;i<packs.size();i++){
PackageInfo p = packs.get(i);
bldr = bldr + "<" + p.packageName + ">" + "\t" + "v" + p.versionName + "\n";
}
TextView tv = new TextView(this);
tv.setMaxLines(packs.size() + 2);
tv.setMovementMethod(new ScrollingMovementMethod());
tv.setText(bldr);
setContentView(tv);
Log.w("com.tmobile.pr.showAllPackages", bldr.toString());
}
}
Related
I have an app that crashes at random times when I don't have a computer nearby to view logcat. Therefore I want to write the reason for a fatal error / every error to a file on my phone that I can read later to debug. I tried using try catch, but I am looking for a complete solution, like a command I enter once and it captures every crash and saves it, like an observer above the code respectively a kind of virtual box.
Which command helps me here?
Using a file for this is a bad idea - Not only do you possible have to worry about extra permissions but you also have to write a fair amount of code.
There are many libraries out there to catch Exceptions and log them for you.
Furthermore in a live environment this won't work at catching bugs since you can't ask users to send them a log file.
I use Fabric (Firebase)
https://firebase.google.com/docs/crashlytics/get-started
You're probably looking for Thread.UncaughtExceptionHandler or even better, Firebase Crashlytics.
I to wanted something similar, the solution that I came up with that works a bit was a Debug Log activity in the app that reads the logcat output in to a TextView.
I then Start this activity from a Menu Item or Button to show previous crashes.
Normally Android Studio Logcat window is just opening a remote shell on to the device with ADB and running the logcat command on the Android Device.
This method runs the logcat command on the Device itself without the need of a remote shell, but you need some Java code in your app to do this.
(This Extra Activity has to be in the Same App as you only have permission to see you own App's logcat)
(This does not always seem to pick up always all Log output but it does pickup crashes)
NOTE
The try and catch in this example code has nothing to do with trying to catch the errors Alex is Hunting as some people thought but to catch a possible error in the logcat display code. The logcat text shown by this Activity will show stack traces of those errors Alex is hunting.
This could then be run after restarting the app.
Code to do this is (Note you need to replace the "YOUR_APPS_TAG" with the Log TAG used by your app) See https://developer.android.com/studio/command-line/logcat for the filter specs
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.widget.TextView;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
public class DebugLogActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_debug_log);
try {
Process process = Runtime.getRuntime().exec("logcat -d -D -v long " + "YOUR_APPS_TAG" + ":V *:E");
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
StringBuilder log=new StringBuilder();
String line = "";
while ((line = bufferedReader.readLine()) != null) {
log.append(line );
log.append(System.getProperty("line.separator"));
}
TextView tv = (TextView)findViewById(R.id.debugLog);
tv.setMovementMethod(new ScrollingMovementMethod());
tv.setTextIsSelectable(true);
tv.setText(log.toString());
} catch (IOException e) {
if (BuildConfig.LOG) {
Log.e("YOUR_APPS_TAG", "DebugLogActivity:onCreate:" + e.toString() + Arrays.toString(e.getStackTrace()));
}
}
}
}
The xml (actvitiy_debug_log.xml) for this extra activity
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".debuglogActivity">
<TextView
android:id="#+id/debugLog"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars = "vertical"
/>
</androidx.appcompat.widget.LinearLayoutCompat>
Example ScreenShot of running Activity after a crash
You can then copy and paste the text out and send it to yourself or just read it in the app.
I have two issues with this, my very first android app. The first is that I noticed after I installed the app the battery started draining about twice as fast as before. I read an article on this that stated sometimes programmers make an error which causes this. This being my first app, the probability is pretty high that this is the case.
The second issue is that I can save my variables when the app is turned off, but when the phone is turned off the data is lost.
As for the code, it's mostly bits and pieces from stuff I've found online and tried to incorporate. It's a simple calculator with three variables. Ideally, I'd like to store b and c, but allow the user to overwrite them. Variable a will change with each use, so no need to store that.
Here's my Main:
package com.kwagz.calc;
import android.app.Activity;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends Activity {
String g, e;
String b; //changed(sorry)
String c; //changed
SharedPreferences sh_Pref;
Editor toEdit;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
loadSavedPreferences();
}
public void calculateClickHandler(View view) {
if (view.getId() == R.id.button1) {
EditText a = (EditText)findViewById(R.id.a);
EditText b = (EditText)findViewById(R.id.b);
EditText c = (EditText)findViewById(R.id.c);
TextView output = (TextView)findViewById(R.id.textView9);
double gp = Double.parseDouble(a.getText().toString());
int ab = Integer.parseInt(b.getText().toString());
int ac = Integer.parseInt(c.getText().toString());
double t = ((gp / ab) * ac);
output.setText(String.format("%.2f", t));
}
}
public void sharedPreferences() {
SharedPreferences saved_values =//there's no linebreak here in my code
PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
SharedPreferences.Editor editor=saved_values.edit();
editor.putString("b", b);
editor.putString("c", c);
editor.commit();
}
private void loadSavedPreferences() {
SharedPreferences saved_values =//there's no linebreak here in my code
PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
b = saved_values.getString("b", g);
}
}
From reading what you said, the only logical explanation forming in my head is: You are starting background service from your App, while background service is running it makes app run all the time which explains why variables are stored until phone is turned off (when background service gets killed).
Okay, let's take your questions one at a time. The battery problem could be a number of things, without knowing more details about your program I couldn't possibly diagnose it completely. Android does have some good power saving tips. The key item is to minimize the use of connectivity devices to no more than is required. The two biggest culprits are GPS and Internet connections. If your app isn't running, then the only way it could be running the batteries is if there's threads in the background, or maybe something like an AlarmService.
You are using SharedPreferences correctly, the value should be saved, but I think you should but the saving code in onSaveInstanceState(). If you do that, it should work fine.
EDIT
Upon closer inspection, you're fundementally saving the wrong thing. You should save the value of the EditText, not the EditText itself. In fact, I'd simply remove all references to String a,b,c, move the EditText definitions to the top to replace them, and do something like this:
editor.putString("b", b.getText().toString());
b.setText(saved_values.getString("b", g));
I've conducted several tests in an effort to recreate the issue, with no success. I'm still working on the sharedPreferences thing, but the battery drain (I suspect) was caused by another app which just happened to coincide with the installation of mine.
As I mentioned in my note to arleitiss, my Y!Mail was showing the highest amount of battery drain. A day or two after posting the note my account started acting up and then became "inactive". Once I reset it, the app no longer appears on the Battery list.
Thanks for all the input!
My app is keeping a "third-party app-exclude-list" as package names in a String[] (and serializing it to the SharedPreferences using the method below). This works fine, but for some users, the Google+ isn't getting added to this list. It only happens for the Google+ app. For all I know, the G+ app isn't anything special, it's package name on Google Play is listed as com.google.android.apps.plus, which shouldn't confuse the saving-algorithm. It works fine on my own phone, so I'm stumped at what causes this, but a lot of my users have reported this as an issue :-/!
public void saveExcludedApplicationList(String[] applicationList) {
mExcludedApplicationList = applicationList;
String combined = "";
for (int i=0; i<mExcludedApplicationList.length; i++){
combined = combined + mExcludedApplicationList[i] + ";";
}
mPref.edit().putString(PREF_EXCLUDED_APPLICATION_LIST, combined).commit();
}
Turns out this had nothing to do with the way I was serializing this, but with the "Google+ Messaging" app beging distributed as the same package as G+.
I am trying to run a monkeyrunner script on multiple devices to do some basic operations.I figured out that initialy I will start of writing a script to perform basic action in two connected devices.
from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice
import time
import sys
import time
devices = os.popen('adb devices').read().strip().split('\n')[1:]
device1 = MonkeyRunner.waitForConnection( devices[0].split('\t')[0])
package = 'com.android.browser'
activity = 'com.android.browser.BrowserActivity'
runComponent = package + '/' + activity
device1.startActivity(component=runComponent)
MonkeyRunner.sleep(1)
device2 = MonkeyRunner.waitForConnection( devices[1].split('\t')[0])
package = 'com.android.browser'
activity = 'com.android.browser.BrowserActivity'
runComponent = package + '/' + activity
device2.startActivity(component=runComponent)
When i run this script, it never finish executing. The browser action happen on one of the connected device but not on other. Can you guys help me fix this or if you have a better code(ideas) to run an activity on multiple devices, Please do let me know~ I am newbie and completely new to the programming world!Thanks in advance
you can give like
device1 = MonkeyRunner.waitForConnection('', devices[0].split('\t')[0])
this will help
A better way to do it is to write a script that explicitly binds to the devices. The link below shows how for emulators
http://chanakaudaya.wordpress.com/2012/04/10/monkeyrunner-tutorial-running-tests-on-multiple-devices-with-monkeyrunner-13/
also seems similar to this question(Which i answered):
Can not simultaneously run monkeyrunner scripts (e.g. two monkeyrunner process) on multi device
I've integrated OpenFeint into my Android game, and I'm wondering what i need to add in order to get the OpenFeint player id. I want the id or the username so I can allow users to transfer their game accounts between devices, authenticating with OpenFeint.
Here's my code for using OpenFeint:
OpenFeintSettings ofsettings = new OpenFeintSettings(gameName, gameKey, gameSecret, gameID);
OpenFeint.initialize(this, ofsettings, new OpenFeintDelegate() {});
#Andy hi i also needed the player id when i implemented openFeint in the game i developed
I used the following code
import com.openfeint.api.OpenFeint;
import com.openfeint.api.resource.User;
import android.app.Activity;
import android.os.Bundle;
public class ABC extends Activity {
User u;
String Name;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.score);
u = OpenFeint.getCurrentUser();
// user id received
Name = u.name;
System.out.println("** The User id is ** " + Name );
}
}
If you're not 100% sold on OpenFeint, check out Swarm, which provides a similar set of features (leaderboards, achievements, cloud data save, etc). Swarm's Cloud Data would do exactly what you're looking for, and allow you to save data to a user's account, so no matter what device they're on, they have all of their data available :)