Skip to content

Commit

Permalink
added new sample for diagnostic Web server
Browse files Browse the repository at this point in the history
  • Loading branch information
commonsguy committed May 16, 2015
1 parent aa7c9fb commit 2aba536
Show file tree
Hide file tree
Showing 37 changed files with 961 additions and 0 deletions.
Binary file added Diagnostics/WebServer/app/DebugActivity.keystore
Binary file not shown.
40 changes: 40 additions & 0 deletions Diagnostics/WebServer/app/build.gradle
@@ -0,0 +1,40 @@
apply plugin: 'com.android.application'

dependencies {
compile 'de.greenrobot:eventbus:2.4.0'
compile 'com.squareup.picasso:picasso:2.5.2'
compile 'com.squareup.retrofit:retrofit:1.9.0'
debugCompile 'com.koushikdutta.async:androidasync:2.1.3'
debugCompile 'com.github.jknack:handlebars:2.1.0'
}

android {
compileSdkVersion 19
buildToolsVersion "21.1.2"

defaultConfig {
versionCode 1
versionName "1.0"
minSdkVersion 11
targetSdkVersion 17
}

signingConfigs {
release {
storeFile file('DebugActivity.keystore')
keyAlias 'HelloConfig'
storePassword 'laser.yams.heady.testy'
keyPassword 'fw.stabs.steady.wool'
}
}

buildTypes {
debug {
applicationIdSuffix ".d"
}

release {
signingConfig signingConfigs.release
}
}
}
20 changes: 20 additions & 0 deletions Diagnostics/WebServer/app/src/debug/AndroidManifest.xml
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.commonsware.android.debug.webserver">

<application>
<activity
android:name="PicassoDiagnosticActivity"
android:label="@string/picasso_diagnostics"
android:theme="@android:style/Theme.NoDisplay"
android:taskAffinity="com.commonsware.android.debug.activity.PicassoDiagnosticActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>

<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<service android:name="PicassoDiagnosticService" />
</application>

</manifest>
24 changes: 24 additions & 0 deletions Diagnostics/WebServer/app/src/debug/assets/picasso.hbs
@@ -0,0 +1,24 @@
<html>
<head><title>Picasso Diagnostics</title></head>
<body>
<h1>Picasso Diagnostics</h1>
<table>
<tr><th style="text-align:right; padding-right:16px;">Timestamp</th><td>{{timeStamp}}</td></tr>
<tr><th style="text-align:right; padding-right:16px;">Average Download Size</th><td>{{averageDownloadSize}}</td></tr>
<tr><th style="text-align:right; padding-right:16px;">Average Original Bitmap Size</th><td>{{averageOriginalBitmapSize}}</td></tr>
<tr><th style="text-align:right; padding-right:16px;">Average Transformed Bitmap Size</th><td>{{averageTransformedBitmapSize}}</td></tr>
<tr><th style="text-align:right; padding-right:16px;">Cache Hits</th><td>{{cacheHits}}</td></tr>
<tr><th style="text-align:right; padding-right:16px;">Cache Misses</th><td>{{cacheMisses}}</td></tr>
<tr><th style="text-align:right; padding-right:16px;">Download Count</th><td>{{downloadCount}}</td></tr>
<tr><th style="text-align:right; padding-right:16px;">Max Size</th><td>{{maxSize}}</td></tr>
<tr><th style="text-align:right; padding-right:16px;">Original Bitmap Count</th><td>{{originalBitmapCount}}</td></tr>
<tr><th style="text-align:right; padding-right:16px;">Size</th><td>{{size}}</td></tr>
<tr><th style="text-align:right; padding-right:16px;">Total Download Size</th><td>{{totalDownloadSize}}</td></tr>
<tr><th style="text-align:right; padding-right:16px;">Total Original Bitmap Size</th><td>{{totalOriginalBitmapSize}}</td></tr>
<tr><th style="text-align:right; padding-right:16px;">Total Transformed Bitmap Size</th><td>{{totalTransformedBitmapSize}}</td></tr>
<tr><th style="text-align:right; padding-right:16px;">Transformed Bitmap Count</th><td>{{transformedBitmapCount}}</td></tr>
</table>
<hr/>
<a href="/stop">Stop Service</a>
</body>
</html>
@@ -0,0 +1,31 @@
/***
Copyright (c) 2015 CommonsWare, LLC
Licensed under the Apache License, Version 2.0 (the "License"); you may not
use this file except in compliance with the License. You may obtain a copy
of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required
by applicable law or agreed to in writing, software distributed under the
License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
OF ANY KIND, either express or implied. See the License for the specific
language governing permissions and limitations under the License.
From _The Busy Coder's Guide to Android Development_
http://commonsware.com/Android
*/

package com.commonsware.android.debug.webserver;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Toast;

public class PicassoDiagnosticActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

startService(new Intent(this, PicassoDiagnosticService.class));
Toast.makeText(this, "Service running!", Toast.LENGTH_LONG).show();
finish();
}
}
@@ -0,0 +1,141 @@
/***
Copyright (c) 2015 CommonsWare, LLC
Licensed under the Apache License, Version 2.0 (the "License"); you may not
use this file except in compliance with the License. You may obtain a copy
of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required
by applicable law or agreed to in writing, software distributed under the
License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
OF ANY KIND, either express or implied. See the License for the specific
language governing permissions and limitations under the License.
From _The Busy Coder's Guide to Android Development_
http://commonsware.com/Android
*/

package com.commonsware.android.debug.webserver;

import android.app.Service;
import android.content.Intent;
import android.content.res.AssetManager;
import android.os.IBinder;
import android.text.format.DateUtils;
import android.util.Log;
import com.github.jknack.handlebars.Context;
import com.github.jknack.handlebars.Handlebars;
import com.github.jknack.handlebars.Template;
import com.github.jknack.handlebars.context.FieldValueResolver;
import com.github.jknack.handlebars.io.AbstractTemplateLoader;
import com.github.jknack.handlebars.io.StringTemplateSource;
import com.github.jknack.handlebars.io.TemplateSource;
import com.koushikdutta.async.http.server.AsyncHttpServer;
import com.koushikdutta.async.http.server.AsyncHttpServerRequest;
import com.koushikdutta.async.http.server.AsyncHttpServerResponse;
import com.koushikdutta.async.http.server.HttpServerRequestCallback;
import com.squareup.picasso.Picasso;
import com.squareup.picasso.StatsSnapshot;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class PicassoDiagnosticService extends Service {
private AsyncHttpServer server;
private Handlebars handlebars;
private Template t;

@Override
public void onCreate() {
super.onCreate();

handlebars=new Handlebars(new AssetTemplateLoader(getAssets()));
server=new AsyncHttpServer();

try {
t=handlebars.compile("picasso.hbs");
server.get("/", new MainRequestCallback());
server.get("/stop", new StopRequestCallback());
server.listen(4999);
}
catch (IOException e) {
Log.e(getClass().getSimpleName(),
"Exception starting Web server", e);
}
}

@Override
public void onDestroy() {
server.stop();

super.onDestroy();
}

@Override
public IBinder onBind(Intent intent) {
return(null);
}

private class MainRequestCallback implements HttpServerRequestCallback {
@Override
public void onRequest(AsyncHttpServerRequest request, AsyncHttpServerResponse response) {
try {
StatsSnapshot ss=Picasso
.with(PicassoDiagnosticService.this)
.getSnapshot();
String formattedTime=DateUtils.formatDateTime(PicassoDiagnosticService.this,
ss.timeStamp,
DateUtils.FORMAT_SHOW_TIME);

Context ctxt=Context
.newBuilder(ss)
.combine("formattedTime", formattedTime)
.resolver(FieldValueResolver.INSTANCE)
.build();

response.send(t.apply(ctxt));
ctxt.destroy();
}
catch (IOException e) {
Log.e(getClass().getSimpleName(),
"Exception serving Web page", e);
}
}
}

private class StopRequestCallback implements HttpServerRequestCallback {
@Override
public void onRequest(AsyncHttpServerRequest request, AsyncHttpServerResponse response) {
response.send("Goodbye, cruel world!");
stopSelf();
}
}

private static class AssetTemplateLoader
extends AbstractTemplateLoader {
private final AssetManager mgr;

AssetTemplateLoader(AssetManager mgr) {
this.mgr=mgr;
}

@Override
public TemplateSource sourceAt(String s) throws IOException {
return(new StringTemplateSource(s, slurp(mgr.open(s))));
}
}

// inspired by http://stackoverflow.com/a/309718/115145

public static String slurp(final InputStream is) throws IOException {
final char[] buffer=new char[1024];
final StringBuilder out=new StringBuilder();
final InputStreamReader in=new InputStreamReader(is, "UTF-8");

while (true) {
int rsz=in.read(buffer, 0, buffer.length);
if (rsz < 0)
break;
out.append(buffer, 0, rsz);
}

return(out.toString());
}
}

0 comments on commit 2aba536

Please sign in to comment.