📜 ⬆️ ⬇️

We write your Android Market

As part of working on a large number of android applications, there was a desire to create your Android Market on a local server (with chess and poetess).
Your market should solve two simple tasks:


And so, we need to implement a small Android application that will download the list of available applications, check for updates for already installed, install / uninstall applications.

Server part


The server part of the application can be both a service with broad functionality (user registration, reports, access control for applications), or simply an xml file:
<MyMarket> <application name="TestApp1" package="com.example.testapp1" versionCode="1" versionName="1.0" url="http://mobile...../android/download/TestApp1.apk"/> ..... </MyMarket> 

In my case, the server part is actually the http ball.
This xml file in the application is transformed into a list of applications available for installation.

Installation


The user selects the application he needs and installs
The market downloads the apk file to the device’s USB flash drive and initiates the installation of the application, of course, installation from third-party sources should be allowed.
We cannot install imperceptibly in the background, so after the execution of this code:
  URL url = new URL(apkurl); HttpURLConnection c = (HttpURLConnection) url.openConnection(); c.setRequestMethod("GET"); c.setDoOutput(true); c.connect(); File file = this.getExternalFilesDir("download"); File outputFile = new File(file, "app.apk"); FileOutputStream fos = new FileOutputStream(outputFile); InputStream is = c.getInputStream(); byte[] buffer = new byte[1024]; int len1 = 0; while ((len1 = is.read(buffer)) != -1) { fos.write(buffer, 0, len1); } fos.close(); is.close(); Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(Uri.fromFile(outputFile), "application/vnd.android.package-archive"); startActivity(intent); 

The user will see the standard application installation window:
image
')

Update


The Market application can check for new versions at a certain interval; this is done quite simply, since a list of all installed applications is available:
  private boolean checkNewVersion(String packageName, int versionCodeNew) { List<ApplicationInfo> apps = getPackageManager() .getInstalledApplications(0); for (int i = 0; i < apps.size(); i++) { ApplicationInfo app = apps.get(i); if (packageName.equals(app.packageName)) { PackageManager manager = getPackageManager(); PackageInfo info; try { info = manager.getPackageInfo(app.packageName, 0); int versionCode = info.versionCode; if (versionCodeNew > versionCode) { Toast.makeText(this, "New Version!", Toast.LENGTH_LONG) .show(); return true; } } catch (NameNotFoundException e) { e.printStackTrace(); } } } return false; } 

If the application needs updating, we repeat the Installation process, the application will be updated.

Deletion


It is better to remove the program from the interface of our market, in order not to force the user to search for the application under test among all its programs, for this it is enough to call this code:
  Uri packageURI = Uri.parse("package:"+packageName); Intent intent = new Intent(Intent.ACTION_DELETE, packageURI); startActivity(intent); 

image

Feedback


Receiving error messages, along with the error log, it is very important for the developer, especially at the stage of testing the application, we will add the function of automatically collecting this information through the Market.

To do this, we add the following class to each application distributed through our Market.
 public class CustomExceptionHandler implements UncaughtExceptionHandler { private File logsFolder = null; public static final String ERROR_INTENT = "com.example.markettestapp1.SEND_ERROR"; public CustomExceptionHandler(File logsFolder) { this.logsFolder = logsFolder; } @Override public void uncaughtException(Thread thread, Throwable ex) { final Writer result = new StringWriter(); final PrintWriter printWriter = new PrintWriter(result); ex.printStackTrace(printWriter); String stacktrace = result.toString(); printWriter.close(); try { if (!logsFolder.exists()) { logsFolder.createNewFile(); } BufferedWriter writer = new BufferedWriter(new FileWriter(logsFolder, true)); writer.write(""+new Date()+"\n"+stacktrace); writer.close(); } catch (IOException e) { e.printStackTrace(); } Intent intent = new Intent(); intent.setAction(ERROR_INTENT); intent.putExtra("packageName", Test1Application.getApplication().getPackageName()); intent.putExtra("stacktrace", stacktrace); Test1Application.getInstanceApplication().sendBroadcast(intent); android.os.Process.killProcess(android.os.Process.myPid()); } } 

As can be seen from the code, this is a handler that receives errors (Exception), generates a string with a stack, saves it to a local file and sends an error in the form of a broadcasted message.

And in the Application class, we include the forwarding of all error messages to this handler.
 public class Test1Application extends Application { @Override public void onCreate() { super.onCreate(); application = this; Thread.setDefaultUncaughtExceptionHandler(new CustomExceptionHandler(new File(this.getApplicationContext().getExternalFilesDir(null),"exceptions.log"))); } 

Thus, if an error occurs in the application under test, before the death, a message is written to the log and a message is sent to the market.
Before transferring the application to the customer, this code is deleted (commented).

In the Market itself, we simply catch this message:
 public class SendErrorReceiver extends BroadcastReceiver { public static final String ERROR_INTENT = "com.example.markettestapp1.SEND_ERROR"; @Override public void onReceive(Context context, Intent intent) { Intent i = new Intent(context, SendErrorActivity.class); i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); i.putExtra("stacktrace", intent.getStringExtra("stacktrace")); i.putExtra("packageName", intent.getStringExtra("packageName")); context.startActivity(i); } } 

AndroidManifest.xml:
  <receiver android:name="com.example.markettestapp1.SendErrorReceiver" android:enabled="true" > <intent-filter> <action android:name="com.example.markettestapp1.SEND_ERROR" > </action> </intent-filter> </receiver> 


And then the market can already send this message to the developer’s mail, upload it to some web service or ask the user to add a comment to the error.
image

I hope this example will help many novice developers to figure out how to write your universal bike for beta application testing and centralized error statistics.

ps: The article used the source code and images taken from the prototype of the application.

Source: https://habr.com/ru/post/163397/


All Articles