From 2aba53683aef3a2701104db704efd50943b4fe77 Mon Sep 17 00:00:00 2001 From: Mark Murphy Date: Sat, 16 May 2015 16:30:19 -0400 Subject: [PATCH] added new sample for diagnostic Web server --- .../WebServer/app/DebugActivity.keystore | Bin 0 -> 3940 bytes Diagnostics/WebServer/app/build.gradle | 40 +++ .../app/src/debug/AndroidManifest.xml | 20 ++ .../app/src/debug/assets/picasso.hbs | 24 ++ .../webserver/PicassoDiagnosticActivity.java | 31 +++ .../webserver/PicassoDiagnosticService.java | 141 +++++++++++ .../app/src/debug/res/layout/main.xml | 238 ++++++++++++++++++ .../app/src/debug/res/values/strings.xml | 7 + .../app/src/debug/res/values/styles.xml | 15 ++ .../app/src/main/AndroidManifest.xml | 23 ++ .../android/debug/webserver/Item.java | 26 ++ .../android/debug/webserver/MainActivity.java | 51 ++++ .../android/debug/webserver/Owner.java | 21 ++ .../debug/webserver/QuestionClickedEvent.java | 23 ++ .../debug/webserver/QuestionsFragment.java | 102 ++++++++ .../android/debug/webserver/SOQuestions.java | 21 ++ .../webserver/StackOverflowInterface.java | 24 ++ .../main/res/drawable-hdpi/ic_launcher.png | Bin 0 -> 5154 bytes .../main/res/drawable-ldpi/ic_launcher.png | Bin 0 -> 1994 bytes .../main/res/drawable-mdpi/ic_launcher.png | Bin 0 -> 2800 bytes .../main/res/drawable-mdpi/owner_error.png | Bin 0 -> 1141 bytes .../res/drawable-mdpi/owner_placeholder.png | Bin 0 -> 812 bytes .../main/res/drawable-xhdpi/ic_launcher.png | Bin 0 -> 7812 bytes .../main/res/drawable-xhdpi/owner_error.png | Bin 0 -> 2051 bytes .../res/drawable-xhdpi/owner_placeholder.png | Bin 0 -> 1369 bytes .../WebServer/app/src/main/res/layout/row.xml | 22 ++ .../app/src/main/res/values-v11/styles.xml | 11 + .../app/src/main/res/values-v14/styles.xml | 12 + .../app/src/main/res/values/dimens.xml | 5 + .../app/src/main/res/values/strings.xml | 7 + .../app/src/main/res/values/styles.xml | 19 ++ Diagnostics/WebServer/build.gradle | 19 ++ Diagnostics/WebServer/gradle.properties | 18 ++ .../gradle/wrapper/gradle-wrapper.properties | 6 + Diagnostics/WebServer/proguard-project.txt | 20 ++ Diagnostics/WebServer/project.properties | 14 ++ Diagnostics/WebServer/settings.gradle | 1 + 37 files changed, 961 insertions(+) create mode 100644 Diagnostics/WebServer/app/DebugActivity.keystore create mode 100644 Diagnostics/WebServer/app/build.gradle create mode 100644 Diagnostics/WebServer/app/src/debug/AndroidManifest.xml create mode 100644 Diagnostics/WebServer/app/src/debug/assets/picasso.hbs create mode 100644 Diagnostics/WebServer/app/src/debug/java/com/commonsware/android/debug/webserver/PicassoDiagnosticActivity.java create mode 100644 Diagnostics/WebServer/app/src/debug/java/com/commonsware/android/debug/webserver/PicassoDiagnosticService.java create mode 100644 Diagnostics/WebServer/app/src/debug/res/layout/main.xml create mode 100644 Diagnostics/WebServer/app/src/debug/res/values/strings.xml create mode 100644 Diagnostics/WebServer/app/src/debug/res/values/styles.xml create mode 100644 Diagnostics/WebServer/app/src/main/AndroidManifest.xml create mode 100644 Diagnostics/WebServer/app/src/main/java/com/commonsware/android/debug/webserver/Item.java create mode 100644 Diagnostics/WebServer/app/src/main/java/com/commonsware/android/debug/webserver/MainActivity.java create mode 100644 Diagnostics/WebServer/app/src/main/java/com/commonsware/android/debug/webserver/Owner.java create mode 100644 Diagnostics/WebServer/app/src/main/java/com/commonsware/android/debug/webserver/QuestionClickedEvent.java create mode 100644 Diagnostics/WebServer/app/src/main/java/com/commonsware/android/debug/webserver/QuestionsFragment.java create mode 100644 Diagnostics/WebServer/app/src/main/java/com/commonsware/android/debug/webserver/SOQuestions.java create mode 100644 Diagnostics/WebServer/app/src/main/java/com/commonsware/android/debug/webserver/StackOverflowInterface.java create mode 100644 Diagnostics/WebServer/app/src/main/res/drawable-hdpi/ic_launcher.png create mode 100644 Diagnostics/WebServer/app/src/main/res/drawable-ldpi/ic_launcher.png create mode 100644 Diagnostics/WebServer/app/src/main/res/drawable-mdpi/ic_launcher.png create mode 100644 Diagnostics/WebServer/app/src/main/res/drawable-mdpi/owner_error.png create mode 100644 Diagnostics/WebServer/app/src/main/res/drawable-mdpi/owner_placeholder.png create mode 100644 Diagnostics/WebServer/app/src/main/res/drawable-xhdpi/ic_launcher.png create mode 100644 Diagnostics/WebServer/app/src/main/res/drawable-xhdpi/owner_error.png create mode 100644 Diagnostics/WebServer/app/src/main/res/drawable-xhdpi/owner_placeholder.png create mode 100644 Diagnostics/WebServer/app/src/main/res/layout/row.xml create mode 100644 Diagnostics/WebServer/app/src/main/res/values-v11/styles.xml create mode 100644 Diagnostics/WebServer/app/src/main/res/values-v14/styles.xml create mode 100644 Diagnostics/WebServer/app/src/main/res/values/dimens.xml create mode 100644 Diagnostics/WebServer/app/src/main/res/values/strings.xml create mode 100644 Diagnostics/WebServer/app/src/main/res/values/styles.xml create mode 100644 Diagnostics/WebServer/build.gradle create mode 100644 Diagnostics/WebServer/gradle.properties create mode 100644 Diagnostics/WebServer/gradle/wrapper/gradle-wrapper.properties create mode 100644 Diagnostics/WebServer/proguard-project.txt create mode 100644 Diagnostics/WebServer/project.properties create mode 100644 Diagnostics/WebServer/settings.gradle diff --git a/Diagnostics/WebServer/app/DebugActivity.keystore b/Diagnostics/WebServer/app/DebugActivity.keystore new file mode 100644 index 0000000000000000000000000000000000000000..c0b10705fa6bd7d7e4be3bd6b95a082ae08dc60e GIT binary patch literal 3940 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 i10%OGz`P_TdThfOcfE + + + + + + + + + + + + + + diff --git a/Diagnostics/WebServer/app/src/debug/assets/picasso.hbs b/Diagnostics/WebServer/app/src/debug/assets/picasso.hbs new file mode 100644 index 000000000..e9b2b681e --- /dev/null +++ b/Diagnostics/WebServer/app/src/debug/assets/picasso.hbs @@ -0,0 +1,24 @@ + +Picasso Diagnostics + +

Picasso Diagnostics

+ + + + + + + + + + + + + + + +
Timestamp{{timeStamp}}
Average Download Size{{averageDownloadSize}}
Average Original Bitmap Size{{averageOriginalBitmapSize}}
Average Transformed Bitmap Size{{averageTransformedBitmapSize}}
Cache Hits{{cacheHits}}
Cache Misses{{cacheMisses}}
Download Count{{downloadCount}}
Max Size{{maxSize}}
Original Bitmap Count{{originalBitmapCount}}
Size{{size}}
Total Download Size{{totalDownloadSize}}
Total Original Bitmap Size{{totalOriginalBitmapSize}}
Total Transformed Bitmap Size{{totalTransformedBitmapSize}}
Transformed Bitmap Count{{transformedBitmapCount}}
+
+Stop Service + + diff --git a/Diagnostics/WebServer/app/src/debug/java/com/commonsware/android/debug/webserver/PicassoDiagnosticActivity.java b/Diagnostics/WebServer/app/src/debug/java/com/commonsware/android/debug/webserver/PicassoDiagnosticActivity.java new file mode 100644 index 000000000..0720479f6 --- /dev/null +++ b/Diagnostics/WebServer/app/src/debug/java/com/commonsware/android/debug/webserver/PicassoDiagnosticActivity.java @@ -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(); + } +} diff --git a/Diagnostics/WebServer/app/src/debug/java/com/commonsware/android/debug/webserver/PicassoDiagnosticService.java b/Diagnostics/WebServer/app/src/debug/java/com/commonsware/android/debug/webserver/PicassoDiagnosticService.java new file mode 100644 index 000000000..03b1f81a3 --- /dev/null +++ b/Diagnostics/WebServer/app/src/debug/java/com/commonsware/android/debug/webserver/PicassoDiagnosticService.java @@ -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()); + } +} diff --git a/Diagnostics/WebServer/app/src/debug/res/layout/main.xml b/Diagnostics/WebServer/app/src/debug/res/layout/main.xml new file mode 100644 index 000000000..30a6a1d37 --- /dev/null +++ b/Diagnostics/WebServer/app/src/debug/res/layout/main.xml @@ -0,0 +1,238 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Diagnostics/WebServer/app/src/debug/res/values/strings.xml b/Diagnostics/WebServer/app/src/debug/res/values/strings.xml new file mode 100644 index 000000000..167e1c9f8 --- /dev/null +++ b/Diagnostics/WebServer/app/src/debug/res/values/strings.xml @@ -0,0 +1,7 @@ + + + + Picasso Demo DEBUG + Picasso Diagnostics + + diff --git a/Diagnostics/WebServer/app/src/debug/res/values/styles.xml b/Diagnostics/WebServer/app/src/debug/res/values/styles.xml new file mode 100644 index 000000000..b486998ef --- /dev/null +++ b/Diagnostics/WebServer/app/src/debug/res/values/styles.xml @@ -0,0 +1,15 @@ + + + + + + + + \ No newline at end of file diff --git a/Diagnostics/WebServer/app/src/main/AndroidManifest.xml b/Diagnostics/WebServer/app/src/main/AndroidManifest.xml new file mode 100644 index 000000000..e0d7e99a3 --- /dev/null +++ b/Diagnostics/WebServer/app/src/main/AndroidManifest.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + diff --git a/Diagnostics/WebServer/app/src/main/java/com/commonsware/android/debug/webserver/Item.java b/Diagnostics/WebServer/app/src/main/java/com/commonsware/android/debug/webserver/Item.java new file mode 100644 index 000000000..0a6538343 --- /dev/null +++ b/Diagnostics/WebServer/app/src/main/java/com/commonsware/android/debug/webserver/Item.java @@ -0,0 +1,26 @@ +/*** + Copyright (c) 2013 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; + +public class Item { + String title; + Owner owner; + String link; + + @Override + public String toString() { + return(title); + } +} diff --git a/Diagnostics/WebServer/app/src/main/java/com/commonsware/android/debug/webserver/MainActivity.java b/Diagnostics/WebServer/app/src/main/java/com/commonsware/android/debug/webserver/MainActivity.java new file mode 100644 index 000000000..d0d7b0cbe --- /dev/null +++ b/Diagnostics/WebServer/app/src/main/java/com/commonsware/android/debug/webserver/MainActivity.java @@ -0,0 +1,51 @@ +/*** + Copyright (c) 2013-2014 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.net.Uri; +import android.os.Bundle; +import de.greenrobot.event.EventBus; + +public class MainActivity extends Activity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + if (getFragmentManager().findFragmentById(android.R.id.content) == null) { + getFragmentManager().beginTransaction() + .add(android.R.id.content, + new QuestionsFragment()).commit(); + } + } + + @Override + public void onResume() { + super.onResume(); + EventBus.getDefault().register(this); + } + + @Override + public void onPause() { + EventBus.getDefault().unregister(this); + super.onPause(); + } + + public void onEventMainThread(QuestionClickedEvent event) { + startActivity(new Intent(Intent.ACTION_VIEW, + Uri.parse(event.item.link))); + } +} diff --git a/Diagnostics/WebServer/app/src/main/java/com/commonsware/android/debug/webserver/Owner.java b/Diagnostics/WebServer/app/src/main/java/com/commonsware/android/debug/webserver/Owner.java new file mode 100644 index 000000000..ca0e50411 --- /dev/null +++ b/Diagnostics/WebServer/app/src/main/java/com/commonsware/android/debug/webserver/Owner.java @@ -0,0 +1,21 @@ +/*** + Copyright (c) 2013 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 com.google.gson.annotations.SerializedName; + +public class Owner { + @SerializedName("profile_image") String profileImage; +} diff --git a/Diagnostics/WebServer/app/src/main/java/com/commonsware/android/debug/webserver/QuestionClickedEvent.java b/Diagnostics/WebServer/app/src/main/java/com/commonsware/android/debug/webserver/QuestionClickedEvent.java new file mode 100644 index 000000000..296397ad2 --- /dev/null +++ b/Diagnostics/WebServer/app/src/main/java/com/commonsware/android/debug/webserver/QuestionClickedEvent.java @@ -0,0 +1,23 @@ +/*** + Copyright (c) 2013-2014 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; + +public class QuestionClickedEvent { + final Item item; + + QuestionClickedEvent(Item item) { + this.item=item; + } +} diff --git a/Diagnostics/WebServer/app/src/main/java/com/commonsware/android/debug/webserver/QuestionsFragment.java b/Diagnostics/WebServer/app/src/main/java/com/commonsware/android/debug/webserver/QuestionsFragment.java new file mode 100644 index 000000000..ce8a1abe3 --- /dev/null +++ b/Diagnostics/WebServer/app/src/main/java/com/commonsware/android/debug/webserver/QuestionsFragment.java @@ -0,0 +1,102 @@ +/*** + Copyright (c) 20132-14 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.ListFragment; +import android.os.Bundle; +import android.text.Html; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.ListView; +import android.widget.TextView; +import android.widget.Toast; +import java.util.List; +import com.squareup.picasso.Picasso; +import de.greenrobot.event.EventBus; +import retrofit.Callback; +import retrofit.RestAdapter; +import retrofit.RetrofitError; +import retrofit.client.Response; + +public class QuestionsFragment extends ListFragment implements + Callback { + @Override + public View onCreateView(LayoutInflater inflater, + ViewGroup container, + Bundle savedInstanceState) { + View result= + super.onCreateView(inflater, container, savedInstanceState); + + setRetainInstance(true); + + RestAdapter restAdapter= + new RestAdapter.Builder().setEndpoint("https://api.stackexchange.com") + .build(); + StackOverflowInterface so= + restAdapter.create(StackOverflowInterface.class); + + so.questions("android", this); + + return(result); + } + + @Override + public void onListItemClick(ListView l, View v, int position, long id) { + Item item=((ItemsAdapter)getListAdapter()).getItem(position); + + EventBus.getDefault().post(new QuestionClickedEvent(item)); + } + + @Override + public void failure(RetrofitError exception) { + Toast.makeText(getActivity(), exception.getMessage(), + Toast.LENGTH_LONG).show(); + Log.e(getClass().getSimpleName(), + "Exception from Retrofit request to StackOverflow", exception); + } + + @Override + public void success(SOQuestions questions, Response response) { + setListAdapter(new ItemsAdapter(questions.items)); + } + + class ItemsAdapter extends ArrayAdapter { + ItemsAdapter(List items) { + super(getActivity(), R.layout.row, R.id.title, items); + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + View row=super.getView(position, convertView, parent); + Item item=getItem(position); + ImageView icon=(ImageView)row.findViewById(R.id.icon); + + Picasso.with(getActivity()).load(item.owner.profileImage) + .fit().centerCrop() + .placeholder(R.drawable.owner_placeholder) + .error(R.drawable.owner_error).into(icon); + + TextView title=(TextView)row.findViewById(R.id.title); + + title.setText(Html.fromHtml(getItem(position).title)); + + return(row); + } + } +} diff --git a/Diagnostics/WebServer/app/src/main/java/com/commonsware/android/debug/webserver/SOQuestions.java b/Diagnostics/WebServer/app/src/main/java/com/commonsware/android/debug/webserver/SOQuestions.java new file mode 100644 index 000000000..768d78b78 --- /dev/null +++ b/Diagnostics/WebServer/app/src/main/java/com/commonsware/android/debug/webserver/SOQuestions.java @@ -0,0 +1,21 @@ +/*** + Copyright (c) 2013 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 java.util.List; + +public class SOQuestions { + List items; +} diff --git a/Diagnostics/WebServer/app/src/main/java/com/commonsware/android/debug/webserver/StackOverflowInterface.java b/Diagnostics/WebServer/app/src/main/java/com/commonsware/android/debug/webserver/StackOverflowInterface.java new file mode 100644 index 000000000..fed2d371c --- /dev/null +++ b/Diagnostics/WebServer/app/src/main/java/com/commonsware/android/debug/webserver/StackOverflowInterface.java @@ -0,0 +1,24 @@ +/*** + Copyright (c) 2013 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 retrofit.Callback; +import retrofit.http.GET; +import retrofit.http.Query; + +public interface StackOverflowInterface { + @GET("/2.1/questions?order=desc&sort=creation&site=stackoverflow") + void questions(@Query("tagged") String tags, Callback cb); +} diff --git a/Diagnostics/WebServer/app/src/main/res/drawable-hdpi/ic_launcher.png b/Diagnostics/WebServer/app/src/main/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..25850f894889a2b15408c46640fca2a0973e66e8 GIT binary patch literal 5154 zcmV+-6y58IP)o&JXe$MUDuU%{ z)ru`(MR)}(KG|duL4xer$z)$<-{*aQH@S2O0TQ7Po}GKo|J<3m`{#at>m7mO(^&}! zaXx1!5C?P)g~S2H0iB-{i7P0sptyq0k3d{O=f^MZgW?K`E9m?P#1(XY{QjMM5Z|jj zVyQ*(MINWo{I>u!bt;L^PV0X|MwambgH1DBr4y4QifAMh2-Q0rf$f!L&c!2cIs6sq zggX=Zp#u^Y%}Fp#x~lhcX(_@zT3uZNXZ8Vk3_`rKX}R^!&iF``-qj zP%NY$G9Y2X1X3^f$z=<3)13FI#A+2814KsLz8*uP1t5&Di^!)WS94Co;qS!fhEFPa zD;ClZ8IZW)?ZP{+=C z-u8IuCfVG20!ZFgUY^mhonPFzAbShN#bo%yQ-y2uQ;v-lm2fQ(iv))u8Iy^`NATea zjO9du)kMw+1)4OpZ(pC)BX2))Cssgi6zvWm#iJRI+U`!edxAk}7^qUH5|k08KNJZy zxV`SpA0PU7%N&}+&W(XxDwDW$PS%emjd8C^votXhm{bQG36KgtXc#{9##Mg}6DtQG zSR35a;e)*@2TraVgq3cL$k_lX-cElzV_>g=PiU3e@u|Ml0PpmK*Is%iD!E_AC2Pxo#@MAa#KzO#m z5pfV5JEnCP-t5c57Hw>1T>_d)Q^iRGCQU2S7d>NZwhdA>sRWHvLz;+&R2mg2j0yw* z0g}NC+xA&~E%ieE>g~e}$Sln>kFWSXES1log3YG7Sbph9C&(_}t5; zZy1)BT3@U;rh6CmYB z13!AOuh91;bCubwYtzAewK%4ZGzJX`**Iz@b~RwImDXca;iD=*ClXKW+u6GF?mNov z*#A8s#XhW4K-_=-{g%|!)B>eanH`NrbHd?p7C@w8WZ-iGe&b;R7-bMsC=_xUbb{lG zeywT42Z|b-wuW?}?W7PO5jCtzt)P&)kc6n6lo8k!2X-GM(?YcETcK{^Qr@aObUe}9Zx?~tJS87qL=^>z3^Ky03>U=(5jo0g~sI084sjdFbJ9n0M`E?^`Ksx(mT)H&jD!kh3 zs4Va^O7Q%QQjHKitS|r-mDdn`@s0A!hh7Lx!ImI*s)-4=nr=;)nKkn-nWdS<2Co4o zYlI@(XRSp`!sR&nNbEKgBLjmGlwj<_Kpq-85u)Z^&4B}n2cEh1z_m;8Yv|EOAGIbY zC-=vVWmv7&Y>h^fp;D>Rbvj)t)+egf>I5upe!pLZZ3s6=EiEn7+S(fOcsy-@!VsDO zsHUNzp$c$H>+9#FIyX}I#!N6 zGayY8%xfe7U5VXz6k@P>?ZnvDK0@Uoa);eiHLB|9_Pe$p7Ik7T$etCEf}7OihD8Q| zo22IEX2KIE+-L}3959P!d~N`!25eUaK&9B{pu^!P#czDmG7SC<&nkVFqbGxr0|YO5 zQs<;o`cJ3R`-AhSsIU*g2SGi?yXc$R$&}%Jm~wkHkQd6S2b^z@Q}}SXu=@FB(I;?; zP1v73)5$Q;^4GqZ{pPB?io6@GQL6-p!N^Ok6$&cqP*4%JW(BdIXK%v_+5te-02Fmo zLqY?syK5aC3LYZdd<4S@7;fCC1D~5=GK~OL2lHtJgi5Tdu-om`PzifA1|SaxA;XaY zF#s7%Y%V6J8NB5C;kaeGZ;Cj!e{%S_`~n&{WKh1+k+6{VfAt5tw(lnroD+D+M=B}M z&`2BJ-AJVBja01Z|%=%%*iq%qlyK@4qB(yk(l4%gYvO;tPg^j zMZb+wz!@M9W;^DUeOK<;UAX%zD5wT%DZx|$I1E63^0CWUC^CT9W$exKb$2J{;(O!l z$DD1T^at-ZOuJ^nFCJRA*<;hTE~Z{qm~(&vULTd#x6lX6KcNpC4oNu-hp$tbWI*h~ zEX%aZ%KP~GnArEofF%DTM==x3Ea&tn7A=JxH-yL^@k@YeF@I+G?1QJ=Pd$(0B7jOK zj5QP4Bswq82BNE!-W;``c^5V zBUQx3x0~H-`O;6(i}T0dxb zB|uw~xBm5sh9@4zR-BPC9N9iW?q$F(svU%9WyCmqjX_K14#$51-`?_;Xlbs89#dT=;ezSFE(%6w(Z%nva-M7xa?#2!SPc5d|E|t3ZQwyyd(Xi z{jFBm4+D}+i}N4M3`mVxg;|LiAy(oX#vH^9wMw%Ob2a9zwyp2XZkhd92cXmXEV6{p zuvAcHre@}>7jM@aOgE_1s-mE%&i08)O+Zvp1mQ>!70BqRP7w^0cpT16<)xJ$>{{>$ zCmpfp;zZK&?6c3Vgpa%a)mLBrX3w5Iw_zJ(JQ5Vy%+FW>!~(MYQu)iRgF}N0QYfW8 zw0D>mgJDR#WH{kl!lbxOLDBV5688f~-m*Y7YA<{f?H^ zjpfJR{Nkm@IGg8lD&KqWy=StrvVQ&Y%P)&nRaLL<-Me=_e&+;5P6y8VtYQI~XJ}^p z@pAv=w`5Z`+_d?mSuvPc^?Ww*Gcw&{qM~6%q$$^sZ<&uGYa3aB-J1QjVn#9#s0 zaFoPwh)j_Xr7FUd7;qhHt0|kacJ@7gnLT@U&ZJ3`KK}5-4-2+z*>d>Ai4#-n>gq~6 zu1QV@x&?@xnc-%`%~P`7*}oe?LlR{b$;x5V;#tIO*Vw5fvxHj4w$Px7gJ?kE0MeFf z$+f{njcXfeclGYI^TYFJHBnPzhm_A@Q6x^D{o9*T(sEyP`h@|lZdN}Yu~J1|ogQ%X zEn}b0k8lV1P6MA8C={>AY?-`n=Rn6%O9oTNC~G?cb|w zYil8(Ei;jCacawo?v{G^I$}d7hk8Q+6%-Dq;qL%YzZ}Y;1k5rd_CE}VXNX(65q8i! z%{ysZ-)*EX)Kl?~ifQCXu1BZ}7xock{SJyvE=am^ghD~_orzanKjBYpQSA-B&_A!6 z9kE+)lmK}E$HSjHAO*Er(x{ZARsdooN}>?I}IybIGW4Zow+D6j4!8KIPBvO}z(aQl`R2wv$mzhQ!f}XF05wQJHg} zcHfq&w5t4qf`Ys$Q>F-G#*87+8jO}j5^`lbjAfTQO0_OOpt#5YFbv7yc96l* zN;><|y<3(&H^tWmTHW`DC%JV7Bxj!%0D@;3Fc%^JN&r$>$RZW5?5t(waKviC498s4 zNR3O^(%Lns%2Sb$J%llC`0(N88*jW3xQhs7g&+RlOGJ`4H*enj>53IALjA`~Ngi_D zP3zkt+RLQ0A!Z7w;nO+*c>qO%WkBFC8R%Mzg04pKnS)C?gpR^G=;Euk5UE{GGBO|r z<#Lb_-xFL-?!b|qPi}a3!GGcK?ar+SQ&-t3I~b;50*s_FG-fh<&(-*x4~K1of;dGC zLp|ujMeQL9eOpfDAAUpMeAn@W*i?-P2?@o3H3Jp=(5tSx$}(=;IO^ZOKcV*Wpeo-1 zP@nFurHm6H!(+ZsnCqrfCXQHcsD~BAro~GhX0x6qSQT_V`pbjRXWot6cNN_3rdFgL zD1sS^-s8fO0bw{>$>Ocsyz%|zH@BAWWfSX8L_MQ|}N_#OB;dS&eJxVt#H(+QL4$4CsSczA)#=MuGv!^ z+FIJm=Q(X+M=YBd`=53Nnb6HN(kQb?BXL#f*s~nD@aHHJ_B(>4?NE?T0>rQ!k}om_ zJx))}(Fgwi*4$M%(Rulx*b9}?{0>lj6a17}9sC10<7v$yv_6pQbTx5^XP?7hBqzVIb(MwEG}QO>PnbUQ)QL|F~|!ulQAl)W+!Yq+R^jm5FuUjJJs$^7`0!+FhMc z2F2#eN;DxCNkCRR1O8@Oa>1}n)3BRJgfs4H;!K&tIz!?dh*czodgMf$3q=s-1#E+E z0Vz4mqqoE%UW#H~j|9p9U!?JSDT?(9XYKa&3x6>l=i-9&dxiP#Lhb2x42qSgl*rBBnI2ZfOaL;*;_fI>l1`~9RvsAovL zY*&*@S{Fg49ci^6+P?CQv97w~+|uZFZP*PCfL8)wp-4{4zq9n6f?!=(rV3boiPs=nTM z>-c5WnWr#H3Wg%rVnHd3RzX21mZeeywOA+& zr36ULb@)Q_~`;|M&bP$ zqpiJla#lzpF_`v3Rj%e)L2!;zvC4qj>oJDJr3agyJcXd7wiAaB>|FKwwd8VfbL^4^ z#5D9HCO`P3Hof3EePXJpfJ)9av07M7Ayo1qEZP5{*@8Jr3I+r-!b>p;R&0<$-h~L~ zBv<9ZO*=kZ@MEl$-k6^2eDeB>p&%(w${u?46}J50?U<*%iX$8sswX80 zwFs!{SxucM_CKEHI`Y&UdgJTWZ#{$c+*-Y)qF7fCizAwC(8PP+O)Mz7UT02}LiUB8 zSUn-1n_8=mG(ti59@_E=|E-0?`~}T}F7$Qt@uYI3-!(V=r#WZn3zqa;jS}JeLQn1L zsil_kgBwdeT|N`Xms_pfKGnrAF}}F=azv|589e^(KPO}l7^Sr)kpf};LQRtI@!|z# z#leQA@&k`l?%05TO8xVFS9i~Iu>kS)v1c~-8#nbHLrV6GmW({DT5rA}rp9o>XrQ?o zs>xY%d{xQ175wsmqgRj04EafR7v_cD?xc$Pj=p7~Eu-&E=3adiD&$4yc0_)mHwxV)q9AV;A?KrN7km1kS})kbHjb6qv0!g9jw$^q*(6 zrHnErWr$i!5;{*hs0r`D&XGt)5$40_y!c&hl5*gf?cUagx#eH2=NE+Rn7Jj>?a&?z z@nS1ThQwhXe+aOptu&k^+xaee+aCXc?{wK)=`?u|-q@d0Z zjzO`ac(5av;qW!f-Aox$>>sUq9I4J`f0rtt&amW`uWX935Mo=u-`m%mX~+K$fG+q= z_vCPx#07*qoM6N<$g4ny=ng9R* literal 0 HcmV?d00001 diff --git a/Diagnostics/WebServer/app/src/main/res/drawable-ldpi/ic_launcher.png b/Diagnostics/WebServer/app/src/main/res/drawable-ldpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..c984844c940237171947ef8351edf1f790d06149 GIT binary patch literal 1994 zcmV;*2Q~PKP)osN672ulWvu_~l0R|W*mGbQ1~A)@zz9+xF@E7o_O-%QU+$j)B!ML37xVL!qLSeZ z+-0VXN!(55d+q&DZ^H8eEHoK9z+!`8WdY2lThm^eR} zaz+4*as)yIAr78_^r&T7(3}ElfCibP)bUq?&#-|T;XudffcXY?DFLJ*350~u+SJih z`4YSoxf4`vZLL8rmlsB((Lx-vK$4{VSS*(3^ZCq?NCaduSxmtQQq5Z5!qWUcMwK=M zVfACU#d%;ON%*7Qn#V zJM1&%4)N!?C0lHr9ZeuhdZbYw^c*`4&pUhJD+1CsbIsT7f?Z<wJT_v@ei_)JIN3l`~b zr^mz4fB17a!u#Md_62BHZa=$!q*yFg8^H($tQ=N_UI9#$fmkF4L989J4*%P-x0juY zopMbmKq^e#7+(CXb%6e=H5(rwD)=L3xWwv&%m)7SK5W#4%UfFa7tQA(2PYc18Ahd`rJ=+r7mg0E- zgbFDIsXV!3zqN2d-fvKVYCa*U+)6F@Ra%hLD$vOpurY~{dVKuQiI$c(-v3@jeO+DM z^3KlAr#v3dAWn}?Q8twrwbhF1cS_l|~ebm%s2 z+}Lk2nf}n--TnKTni>J;vah_?c+fKr&j-e1DFEJL2Tz6#!e$FRVo*USDZ!vO1V-Ks zbNxJUy(fFxf46%brh{uZpJMQqlKSjPC3I8%a#;Q*1I&{e(3tRwksA~6dZHcL-<8|s ztFp7RUtYa>wY{pU>I&wV1I_;$>g6T>HJOc4nJ1`atJY!V=kKf*>?g*s2hrz;+ zfOXUj>3-L~#yvmXhHKJCF+-ur27*)2#^lBcSPD2Yl2(SMK{FwgL#x&9D0t$za>blt z_2dF^MH-BntuTh>Gnyc&!N5jZWiSAyQ69_)WAKiFD(F6WbnmN=<2*_qcLbW+L5fkC z{syU-LrX`qe(U>n9~pAK=9ru);kgvj>cDR>K|rU6s8R(C0;wZm;QU@N_{KmP8Hd>D z)$=X&ub1IG`qb|UX!^M6&jhSr_TrnL>*kgePwf<0HWl1qwHD%ObQq#Su?T2`K~P5N zD3ri^$=P-0(B2As2+bA{t)uz+`pu2DMQheF2r<1RWpW@mDzan}SdsE5N}f!>NM}oP zSM$MVXHy|sTea}<4X<$pOX~Dl`7?=bqcO#kZ|Fk8cd6^u-nPa+;t-0@S#cRHB3G#l zb8?nGaV&e$Du;?Q-_6Z1?)Sh@*FT*XTN^5IFpqXawkhR)eqmGj%kC&!smsiN-(FN^ z)|xZ%e{1HFk|aW4#0A$cI7h?0>xFAyb^POY?jo-H0ZN4jn$ccd{2;jxjOBi(0OagO(P>dXcZtwFiVsMcBM+aD|c5oY$4 z$#^tV6cY-TmB-k$wEsXd(K>XlZC^Ydro)tA?)aa6zY0xypZ;?w(;LzBXp}%nJ=&OZ z4P|=zC#U-vaWh*nbZa!;a6f^OVgy6abf^%(&0^Lo@ c2Tq~?0{y@Ib`j-r=Kufz07*qoM6N<$g6V(J!2kdN literal 0 HcmV?d00001 diff --git a/Diagnostics/WebServer/app/src/main/res/drawable-mdpi/ic_launcher.png b/Diagnostics/WebServer/app/src/main/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..2bb6cb5d3cbc0fa500ede26f873cb6fbbf5b0451 GIT binary patch literal 2800 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 Hu0mjfF%u9M literal 0 HcmV?d00001 diff --git a/Diagnostics/WebServer/app/src/main/res/drawable-mdpi/owner_placeholder.png b/Diagnostics/WebServer/app/src/main/res/drawable-mdpi/owner_placeholder.png new file mode 100644 index 0000000000000000000000000000000000000000..3d220aa495d85b51df62e3415d4f5040d323affb GIT binary patch literal 812 zcmV+{1JnG8P)oNq>&`|ij#Wwg4wdNG9Xfuw2Mo3=ljnwq*XJ3G5Ij*rFx*xcMawY$6f zvZVKb7SKF!dk?r(tya&?&CUHXae$4Djk7VvE>N?5`d`hY5wH!s+iJDGm>9s?+S;`3 zuB5X-NbudZ{YJap{I%ga^UPmCLWKr?xszfc-rW@cs<*e{!IyJ`Ey(g2cn zifRh__eP`9*QEhkt=4bAuq=S>rFOf$UK#*E(h?BM0E7?<`w9VKjMspjal<8zY*&sA zu&}Uj)ApTl0c`J8DwPk94FDkNW5#<6JHY$%^Yi_Q001|DQEIyFTUnM}O{q-+$g=E? zq|1{2NC^Kkgzzblbj&7yb(Te~YCm@ElNhY@U#6ffIh+MfxA03j7K@dH;g# qLqO6$_=Mo*`;QKt+kXLj;R0000qkiE(wzd*v2>R-5=(b?H;9y^guqhL-JODTcfEf9!gnz< zck`T!InSAy6RD;mi-k^t4gdhK? zn_tUG<-lGE;P|!rw^HjZF4A$8Wb%bOSY>+`$-%K5{G2X`|uo5AT+iqivZ+U zT2!*x`6Rt&$Lgat0``jM76$xnq-$k>SxLZk^QcKfysIz|qlssQ))CVEqFo&Cx+Oj> zMk0#xDJ{Afi!bL8g%A(-uK&}6)oJ$luP*}%Imn+2*<1-33Y-w2+Jh~R4|txjAKE-? zbT__#qRs6_o!>}=hCVR$$00PHNEP0I;nKUnZE}z0Hj7D8*_>ZD)MR}W=#eYGL5rfm zn0U9dn**A0k@e@}gcL(MJzg1gLSJz}Z7inn&Im1hcZ59%rhx3I6;akU+Ck}O*?zie z$86LM@-IY2l>~SO1~B-Ok_OfJM5N{No#+Aw3a z%=m`rWB(gD=~nyE+PhJAAKnXn5h143doF_ErY9!QvXlSr5*q4x366xp(;( zd~0mN7V708`zkm|$Tgde!ub9yaVtItB4Bb!$F!a@wCCd*)v2tit`@|U0><>2?&07B zQuCz{m|vDZ8oHOY&AI2bm0t0U1^5ZD%8uUVUOj*~3MtwF2FEjdfBv{Aig^6u-nwRL z-`9@~q*jH?ICh0{;@_$J?~S7Y>r5Dp1Ksmx*uyepvG66p&?l84zRP1VirYr%_~Udy znon=elrKDxtEOX+Jlf)qD0|!vBA&xt;r82f6N&?g0B3+5fE<$ixFpF;} z`!u)H<*|2)&0QKGiVLcPUpmabeqZsBmyh%xPGNeGmzVEdbM$QP-6F;e97YfC&FqG9 z7)pNmP8&)N0#$_dm6&s8k8yKaAgA)b;zhnlW5dn%z2tG>#pW~wbb*LP^(R?zkwha^ zKtKF~kuv+Oy&%!$7*1%2QFjdfcR8*SZ7%o2+1c)3R4auf?mj3-Nv~CD zVQG(XDR9@kD*44fAW5cJ9ZTfmW5p3mR(1QY5X|ygFt#fWmu;z)-JxVu{pxvffCq;jvzQWc3$~m!=RDJY_y7o= z*h-xPYDUt)PT}~tN>Itj;;o09TMNKLRzgBTXddf*bSY>c%ee~Md{#?S^LVMzMq?zO z{lf4uI3VweY2tBQsjnI4-N&@=qKC^O@w%yF3w*! z##hhjCQh{w7^+Q6`DUJmVpC}}z9*ev4A3lnmkWdrB%wK|FL3I0_MjpOhX+sMPc9xD zM+U|FhBOyax>H?-{hG~K(0QtOK5%0D-e&z-6Cx!;Oge9CIhsKgOD^QWC^m!|fq4rB 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 bwcY;!B-5vB + + + + + + + diff --git a/Diagnostics/WebServer/app/src/main/res/values-v11/styles.xml b/Diagnostics/WebServer/app/src/main/res/values-v11/styles.xml new file mode 100644 index 000000000..cca2a1a2f --- /dev/null +++ b/Diagnostics/WebServer/app/src/main/res/values-v11/styles.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/Diagnostics/WebServer/app/src/main/res/values-v14/styles.xml b/Diagnostics/WebServer/app/src/main/res/values-v14/styles.xml new file mode 100644 index 000000000..3eb0f9fe7 --- /dev/null +++ b/Diagnostics/WebServer/app/src/main/res/values-v14/styles.xml @@ -0,0 +1,12 @@ + + + + + + diff --git a/Diagnostics/WebServer/app/src/main/res/values/dimens.xml b/Diagnostics/WebServer/app/src/main/res/values/dimens.xml new file mode 100644 index 000000000..6e00b8dcd --- /dev/null +++ b/Diagnostics/WebServer/app/src/main/res/values/dimens.xml @@ -0,0 +1,5 @@ + + + 48dp + + diff --git a/Diagnostics/WebServer/app/src/main/res/values/strings.xml b/Diagnostics/WebServer/app/src/main/res/values/strings.xml new file mode 100644 index 000000000..b3d163038 --- /dev/null +++ b/Diagnostics/WebServer/app/src/main/res/values/strings.xml @@ -0,0 +1,7 @@ + + + + Picasso Demo + Owner Icon + + diff --git a/Diagnostics/WebServer/app/src/main/res/values/styles.xml b/Diagnostics/WebServer/app/src/main/res/values/styles.xml new file mode 100644 index 000000000..6cb4b0d55 --- /dev/null +++ b/Diagnostics/WebServer/app/src/main/res/values/styles.xml @@ -0,0 +1,19 @@ + + + + + + + + + diff --git a/Diagnostics/WebServer/build.gradle b/Diagnostics/WebServer/build.gradle new file mode 100644 index 000000000..6356aabdc --- /dev/null +++ b/Diagnostics/WebServer/build.gradle @@ -0,0 +1,19 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:1.0.0' + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + jcenter() + } +} diff --git a/Diagnostics/WebServer/gradle.properties b/Diagnostics/WebServer/gradle.properties new file mode 100644 index 000000000..5d08ba75b --- /dev/null +++ b/Diagnostics/WebServer/gradle.properties @@ -0,0 +1,18 @@ +# Project-wide Gradle settings. + +# IDE (e.g. Android Studio) users: +# Settings specified in this file will override any Gradle settings +# configured through the IDE. + +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html + +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +# Default value: -Xmx10248m -XX:MaxPermSize=256m +# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 + +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true \ No newline at end of file diff --git a/Diagnostics/WebServer/gradle/wrapper/gradle-wrapper.properties b/Diagnostics/WebServer/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..0c71e760d --- /dev/null +++ b/Diagnostics/WebServer/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Wed Apr 10 15:27:10 PDT 2013 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip diff --git a/Diagnostics/WebServer/proguard-project.txt b/Diagnostics/WebServer/proguard-project.txt new file mode 100644 index 000000000..f2fe1559a --- /dev/null +++ b/Diagnostics/WebServer/proguard-project.txt @@ -0,0 +1,20 @@ +# To enable ProGuard in your project, edit project.properties +# to define the proguard.config property as described in that file. +# +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in ${sdk.dir}/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the ProGuard +# include property in project.properties. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} diff --git a/Diagnostics/WebServer/project.properties b/Diagnostics/WebServer/project.properties new file mode 100644 index 000000000..4ab125693 --- /dev/null +++ b/Diagnostics/WebServer/project.properties @@ -0,0 +1,14 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system edit +# "ant.properties", and override values to adapt the script to your +# project structure. +# +# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): +#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt + +# Project target. +target=android-19 diff --git a/Diagnostics/WebServer/settings.gradle b/Diagnostics/WebServer/settings.gradle new file mode 100644 index 000000000..e7b4def49 --- /dev/null +++ b/Diagnostics/WebServer/settings.gradle @@ -0,0 +1 @@ +include ':app'