Compare commits
10 Commits
7177bc089d
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 6b9cbdef84 | |||
| ab75dd3bb1 | |||
| 4de767f753 | |||
| 5e6e6c4dd9 | |||
| 507d7901bf | |||
| 9ec67079c0 | |||
| 42cb0b9f0e | |||
| c4980a8295 | |||
| 824f58879c | |||
| 9b7c2594c9 |
@@ -4,5 +4,6 @@
|
||||
<classpathentry kind="src" path="gen"/>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
|
||||
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
|
||||
<classpathentry kind="output" path="bin/classes"/>
|
||||
</classpath>
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0" >
|
||||
|
||||
<uses-sdk android:minSdkVersion="1" />
|
||||
<uses-sdk
|
||||
android:minSdkVersion="7"
|
||||
android:targetSdkVersion="16" />
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
@@ -14,7 +16,9 @@
|
||||
android:configChanges="keyboard|keyboardHidden|orientation" >
|
||||
</activity>
|
||||
|
||||
<service android:name="ReportPostingService" >
|
||||
<service
|
||||
android:name="ReportPostingService"
|
||||
android:process=":reportpostingservice" >
|
||||
</service>
|
||||
</application>
|
||||
|
||||
|
||||
30
ExceptionHandlerLib/ExceptionHandlerLib.iml
Normal file
30
ExceptionHandlerLib/ExceptionHandlerLib.iml
Normal file
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="EclipseModuleManager" forced_jdk="true">
|
||||
<conelement value="com.android.ide.eclipse.adt.DEPENDENCIES" />
|
||||
<src_description expected_position="1">
|
||||
<src_folder value="file://$MODULE_DIR$/src" expected_position="0" />
|
||||
<src_folder value="file://$MODULE_DIR$/gen" expected_position="1" />
|
||||
<src_folder value="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK" expected_position="2" />
|
||||
<src_folder value="com.android.ide.eclipse.adt.LIBRARIES" expected_position="3" />
|
||||
</src_description>
|
||||
</component>
|
||||
<component name="FacetManager">
|
||||
<facet type="android" name="Android">
|
||||
<configuration>
|
||||
<option name="LIBRARY_PROJECT" value="true" />
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="false">
|
||||
<output url="file://$MODULE_DIR$/bin/classes" />
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/gen" isTestSource="false" generated="true" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="Android 4.3 Google APIs" jdkType="Android SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
92
ExceptionHandlerLib/build.xml
Normal file
92
ExceptionHandlerLib/build.xml
Normal file
@@ -0,0 +1,92 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="ExceptionHandlerLib" default="help">
|
||||
|
||||
<!-- The local.properties file is created and updated by the 'android' tool.
|
||||
It contains the path to the SDK. It should *NOT* be checked into
|
||||
Version Control Systems. -->
|
||||
<property file="local.properties" />
|
||||
|
||||
<!-- The ant.properties file can be created by you. It is only edited by the
|
||||
'android' tool to add properties to it.
|
||||
This is the place to change some Ant specific build properties.
|
||||
Here are some properties you may want to change/update:
|
||||
|
||||
source.dir
|
||||
The name of the source directory. Default is 'src'.
|
||||
out.dir
|
||||
The name of the output directory. Default is 'bin'.
|
||||
|
||||
For other overridable properties, look at the beginning of the rules
|
||||
files in the SDK, at tools/ant/build.xml
|
||||
|
||||
Properties related to the SDK location or the project target should
|
||||
be updated using the 'android' tool with the 'update' action.
|
||||
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems.
|
||||
|
||||
-->
|
||||
<property file="ant.properties" />
|
||||
|
||||
<!-- if sdk.dir was not set from one of the property file, then
|
||||
get it from the ANDROID_HOME env var.
|
||||
This must be done before we load project.properties since
|
||||
the proguard config can use sdk.dir -->
|
||||
<property environment="env" />
|
||||
<condition property="sdk.dir" value="${env.ANDROID_HOME}">
|
||||
<isset property="env.ANDROID_HOME" />
|
||||
</condition>
|
||||
|
||||
<!-- The project.properties file is created and updated by the 'android'
|
||||
tool, as well as ADT.
|
||||
|
||||
This contains project specific properties such as project target, and library
|
||||
dependencies. Lower level build properties are stored in ant.properties
|
||||
(or in .classpath for Eclipse projects).
|
||||
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems. -->
|
||||
<loadproperties srcFile="project.properties" />
|
||||
|
||||
<!-- quick check on sdk.dir -->
|
||||
<fail
|
||||
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
|
||||
unless="sdk.dir"
|
||||
/>
|
||||
|
||||
<!--
|
||||
Import per project custom build rules if present at the root of the project.
|
||||
This is the place to put custom intermediary targets such as:
|
||||
-pre-build
|
||||
-pre-compile
|
||||
-post-compile (This is typically used for code obfuscation.
|
||||
Compiled code location: ${out.classes.absolute.dir}
|
||||
If this is not done in place, override ${out.dex.input.absolute.dir})
|
||||
-post-package
|
||||
-post-build
|
||||
-pre-clean
|
||||
-->
|
||||
<import file="custom_rules.xml" optional="true" />
|
||||
|
||||
<!-- Import the actual build file.
|
||||
|
||||
To customize existing targets, there are two options:
|
||||
- Customize only one target:
|
||||
- copy/paste the target into this file, *before* the
|
||||
<import> task.
|
||||
- customize it to your needs.
|
||||
- Customize the whole content of build.xml
|
||||
- copy/paste the content of the rules files (minus the top node)
|
||||
into this file, replacing the <import> task.
|
||||
- customize to your needs.
|
||||
|
||||
***********************
|
||||
****** IMPORTANT ******
|
||||
***********************
|
||||
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
|
||||
in order to avoid having your file be overridden by tools such as "android update project"
|
||||
-->
|
||||
<!-- version-tag: 1 -->
|
||||
<import file="${sdk.dir}/tools/ant/build.xml" />
|
||||
|
||||
</project>
|
||||
3
ExceptionHandlerLib/lint.xml
Normal file
3
ExceptionHandlerLib/lint.xml
Normal file
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<lint>
|
||||
</lint>
|
||||
10
ExceptionHandlerLib/local.properties
Normal file
10
ExceptionHandlerLib/local.properties
Normal file
@@ -0,0 +1,10 @@
|
||||
# This file is automatically generated by Android Tools.
|
||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||
#
|
||||
# This file must *NOT* be checked into Version Control Systems,
|
||||
# as it contains information specific to your local configuration.
|
||||
|
||||
# location of the SDK. This is only used by Ant
|
||||
# For customization when using a Version Control System, please read the
|
||||
# header note.
|
||||
sdk.dir=/app/android-sdk-linux_86
|
||||
20
ExceptionHandlerLib/proguard-project.txt
Normal file
20
ExceptionHandlerLib/proguard-project.txt
Normal file
@@ -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 *;
|
||||
#}
|
||||
@@ -9,4 +9,4 @@
|
||||
|
||||
android.library=true
|
||||
# Project target.
|
||||
target=android-15
|
||||
target=android-17
|
||||
|
||||
0
ExceptionHandlerLib/res/drawable/.NOTEMPTY
Normal file
0
ExceptionHandlerLib/res/drawable/.NOTEMPTY
Normal file
388
ExceptionHandlerLib/src/anroid/v4/compat/NotificationCompat.java
Normal file
388
ExceptionHandlerLib/src/anroid/v4/compat/NotificationCompat.java
Normal file
@@ -0,0 +1,388 @@
|
||||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package anroid.v4.compat;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.media.AudioManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
public class NotificationCompat {
|
||||
/**
|
||||
* Bit to be bitwise-ored into the {@link Notification#flags} field that should be set if
|
||||
* this notification represents a high-priority event that may be shown to the user even
|
||||
* if notifications are otherwise unavailable (that is, when the status bar is hidden).
|
||||
* This flag is ideally used in conjunction with fullScreenIntent.
|
||||
*
|
||||
* <p>This will only be respected on API level 9 and above.</p>
|
||||
*/
|
||||
public static final int FLAG_HIGH_PRIORITY = 0x00000080;
|
||||
|
||||
private static final NotificationCompatImpl IMPL;
|
||||
|
||||
interface NotificationCompatImpl {
|
||||
public Notification getNotification(Builder b);
|
||||
}
|
||||
|
||||
static class NotificationCompatImplBase implements NotificationCompatImpl {
|
||||
public Notification getNotification(Builder b) {
|
||||
Notification result = (Notification) b.mNotification;
|
||||
result.setLatestEventInfo(b.mContext, b.mContentTitle,
|
||||
b.mContentText, b.mContentIntent);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
static class NotificationCompatImplHoneycomb implements NotificationCompatImpl {
|
||||
public Notification getNotification(Builder b) {
|
||||
return NotificationCompatHoneycomb.add(b.mContext, b.mNotification,
|
||||
b.mContentTitle, b.mContentText, b.mContentInfo, b.mTickerView,
|
||||
b.mNumber, b.mContentIntent, b.mFullScreenIntent, b.mLargeIcon);
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
if (Build.VERSION.SDK_INT >= 11) {
|
||||
IMPL = new NotificationCompatImplHoneycomb();
|
||||
} else {
|
||||
IMPL = new NotificationCompatImplBase();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder class for {@link Notification} objects. Allows easier control over
|
||||
* all the flags, as well as help constructing the typical notification layouts.
|
||||
*/
|
||||
public static class Builder {
|
||||
Context mContext;
|
||||
|
||||
CharSequence mContentTitle;
|
||||
CharSequence mContentText;
|
||||
PendingIntent mContentIntent;
|
||||
PendingIntent mFullScreenIntent;
|
||||
RemoteViews mTickerView;
|
||||
Bitmap mLargeIcon;
|
||||
CharSequence mContentInfo;
|
||||
int mNumber;
|
||||
|
||||
Notification mNotification = new Notification();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* Automatically sets the when field to {@link System#currentTimeMillis()
|
||||
* System.currentTimeMillis()} and the audio stream to the
|
||||
* {@link Notification#STREAM_DEFAULT}.
|
||||
*
|
||||
* @param context A {@link Context} that will be used to construct the
|
||||
* RemoteViews. The Context will not be held past the lifetime of this
|
||||
* Builder object.
|
||||
*/
|
||||
public Builder(Context context) {
|
||||
mContext = context;
|
||||
|
||||
// Set defaults to match the defaults of a Notification
|
||||
mNotification.when = System.currentTimeMillis();
|
||||
mNotification.audioStreamType = Notification.STREAM_DEFAULT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the time that the event occurred. Notifications in the panel are
|
||||
* sorted by this time.
|
||||
*/
|
||||
public Builder setWhen(long when) {
|
||||
mNotification.when = when;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the small icon to use in the notification layouts. Different classes of devices
|
||||
* may return different sizes. See the UX guidelines for more information on how to
|
||||
* design these icons.
|
||||
*
|
||||
* @param icon A resource ID in the application's package of the drawble to use.
|
||||
*/
|
||||
public Builder setSmallIcon(int icon) {
|
||||
mNotification.icon = icon;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* A variant of {@link #setSmallIcon(int) setSmallIcon(int)} that takes an additional
|
||||
* level parameter for when the icon is a {@link android.graphics.drawable.LevelListDrawable
|
||||
* LevelListDrawable}.
|
||||
*
|
||||
* @param icon A resource ID in the application's package of the drawble to use.
|
||||
* @param level The level to use for the icon.
|
||||
*
|
||||
* @see android.graphics.drawable.LevelListDrawable
|
||||
*/
|
||||
public Builder setSmallIcon(int icon, int level) {
|
||||
mNotification.icon = icon;
|
||||
mNotification.iconLevel = level;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the title (first row) of the notification, in a standard notification.
|
||||
*/
|
||||
public Builder setContentTitle(CharSequence title) {
|
||||
mContentTitle = title;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the text (second row) of the notification, in a standard notification.
|
||||
*/
|
||||
public Builder setContentText(CharSequence text) {
|
||||
mContentText = text;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the large number at the right-hand side of the notification. This is
|
||||
* equivalent to setContentInfo, although it might show the number in a different
|
||||
* font size for readability.
|
||||
*/
|
||||
public Builder setNumber(int number) {
|
||||
mNumber = number;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the large text at the right-hand side of the notification.
|
||||
*/
|
||||
public Builder setContentInfo(CharSequence info) {
|
||||
mContentInfo = info;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the progress this notification represents, which may be
|
||||
* represented as a {@link ProgressBar}.
|
||||
*/
|
||||
/* TODO
|
||||
public Builder setProgress(int max, int progress, boolean indeterminate) {
|
||||
mProgressMax = max;
|
||||
mProgress = progress;
|
||||
mProgressIndeterminate = indeterminate;
|
||||
return this;
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Supply a custom RemoteViews to use instead of the standard one.
|
||||
*/
|
||||
public Builder setContent(RemoteViews views) {
|
||||
mNotification.contentView = views;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Supply a {@link PendingIntent} to send when the notification is clicked.
|
||||
* If you do not supply an intent, you can now add PendingIntents to individual
|
||||
* views to be launched when clicked by calling {@link RemoteViews#setOnClickPendingIntent
|
||||
* RemoteViews.setOnClickPendingIntent(int,PendingIntent)}. Be sure to
|
||||
* read {@link Notification#contentIntent Notification.contentIntent} for
|
||||
* how to correctly use this.
|
||||
*/
|
||||
public Builder setContentIntent(PendingIntent intent) {
|
||||
mContentIntent = intent;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Supply a {@link PendingIntent} to send when the notification is cleared by the user
|
||||
* directly from the notification panel. For example, this intent is sent when the user
|
||||
* clicks the "Clear all" button, or the individual "X" buttons on notifications. This
|
||||
* intent is not sent when the application calls {@link NotificationManager#cancel
|
||||
* NotificationManager.cancel(int)}.
|
||||
*/
|
||||
public Builder setDeleteIntent(PendingIntent intent) {
|
||||
mNotification.deleteIntent = intent;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* An intent to launch instead of posting the notification to the status bar.
|
||||
* Only for use with extremely high-priority notifications demanding the user's
|
||||
* <strong>immediate</strong> attention, such as an incoming phone call or
|
||||
* alarm clock that the user has explicitly set to a particular time.
|
||||
* If this facility is used for something else, please give the user an option
|
||||
* to turn it off and use a normal notification, as this can be extremely
|
||||
* disruptive.
|
||||
*
|
||||
* @param intent The pending intent to launch.
|
||||
* @param highPriority Passing true will cause this notification to be sent
|
||||
* even if other notifications are suppressed.
|
||||
*/
|
||||
public Builder setFullScreenIntent(PendingIntent intent, boolean highPriority) {
|
||||
mFullScreenIntent = intent;
|
||||
setFlag(FLAG_HIGH_PRIORITY, highPriority);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the text that is displayed in the status bar when the notification first
|
||||
* arrives.
|
||||
*/
|
||||
public Builder setTicker(CharSequence tickerText) {
|
||||
mNotification.tickerText = tickerText;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the text that is displayed in the status bar when the notification first
|
||||
* arrives, and also a RemoteViews object that may be displayed instead on some
|
||||
* devices.
|
||||
*/
|
||||
public Builder setTicker(CharSequence tickerText, RemoteViews views) {
|
||||
mNotification.tickerText = tickerText;
|
||||
mTickerView = views;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the large icon that is shown in the ticker and notification.
|
||||
*/
|
||||
public Builder setLargeIcon(Bitmap icon) {
|
||||
mLargeIcon = icon;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the sound to play. It will play on the default stream.
|
||||
*/
|
||||
public Builder setSound(Uri sound) {
|
||||
mNotification.sound = sound;
|
||||
mNotification.audioStreamType = Notification.STREAM_DEFAULT;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the sound to play. It will play on the stream you supply.
|
||||
*
|
||||
* @see #STREAM_DEFAULT
|
||||
* @see AudioManager for the <code>STREAM_</code> constants.
|
||||
*/
|
||||
public Builder setSound(Uri sound, int streamType) {
|
||||
mNotification.sound = sound;
|
||||
mNotification.audioStreamType = streamType;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the vibration pattern to use.
|
||||
*
|
||||
* @see android.os.Vibrator for a discussion of the <code>pattern</code>
|
||||
* parameter.
|
||||
*/
|
||||
public Builder setVibrate(long[] pattern) {
|
||||
mNotification.vibrate = pattern;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the argb value that you would like the LED on the device to blnk, as well as the
|
||||
* rate. The rate is specified in terms of the number of milliseconds to be on
|
||||
* and then the number of milliseconds to be off.
|
||||
*/
|
||||
public Builder setLights(int argb, int onMs, int offMs) {
|
||||
mNotification.ledARGB = argb;
|
||||
mNotification.ledOnMS = onMs;
|
||||
mNotification.ledOffMS = offMs;
|
||||
boolean showLights = mNotification.ledOnMS != 0 && mNotification.ledOffMS != 0;
|
||||
mNotification.flags = (mNotification.flags & ~Notification.FLAG_SHOW_LIGHTS) |
|
||||
(showLights ? Notification.FLAG_SHOW_LIGHTS : 0);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether this is an ongoing notification.
|
||||
*
|
||||
* <p>Ongoing notifications differ from regular notifications in the following ways:
|
||||
* <ul>
|
||||
* <li>Ongoing notifications are sorted above the regular notifications in the
|
||||
* notification panel.</li>
|
||||
* <li>Ongoing notifications do not have an 'X' close button, and are not affected
|
||||
* by the "Clear all" button.
|
||||
* </ul>
|
||||
*/
|
||||
public Builder setOngoing(boolean ongoing) {
|
||||
setFlag(Notification.FLAG_ONGOING_EVENT, ongoing);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this flag if you would only like the sound, vibrate
|
||||
* and ticker to be played if the notification is not already showing.
|
||||
*/
|
||||
public Builder setOnlyAlertOnce(boolean onlyAlertOnce) {
|
||||
setFlag(Notification.FLAG_ONLY_ALERT_ONCE, onlyAlertOnce);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setting this flag will make it so the notification is automatically
|
||||
* canceled when the user clicks it in the panel. The PendingIntent
|
||||
* set with {@link #setDeleteIntent} will be broadcast when the notification
|
||||
* is canceled.
|
||||
*/
|
||||
public Builder setAutoCancel(boolean autoCancel) {
|
||||
setFlag(Notification.FLAG_AUTO_CANCEL, autoCancel);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default notification options that will be used.
|
||||
* <p>
|
||||
* The value should be one or more of the following fields combined with
|
||||
* bitwise-or:
|
||||
* {@link Notification#DEFAULT_SOUND}, {@link Notification#DEFAULT_VIBRATE},
|
||||
* {@link Notification#DEFAULT_LIGHTS}.
|
||||
* <p>
|
||||
* For all default values, use {@link Notification#DEFAULT_ALL}.
|
||||
*/
|
||||
public Builder setDefaults(int defaults) {
|
||||
mNotification.defaults = defaults;
|
||||
if ((defaults & Notification.DEFAULT_LIGHTS) != 0) {
|
||||
mNotification.flags |= Notification.FLAG_SHOW_LIGHTS;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
private void setFlag(int mask, boolean value) {
|
||||
if (value) {
|
||||
mNotification.flags |= mask;
|
||||
} else {
|
||||
mNotification.flags &= ~mask;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Combine all of the options that have been set and return a new {@link Notification}
|
||||
* object.
|
||||
*/
|
||||
public Notification getNotification() {
|
||||
return (Notification) IMPL.getNotification(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package anroid.v4.compat;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
class NotificationCompatHoneycomb {
|
||||
static Notification add(Context context, Notification n,
|
||||
CharSequence contentTitle, CharSequence contentText, CharSequence contentInfo,
|
||||
RemoteViews tickerView, int number,
|
||||
PendingIntent contentIntent, PendingIntent fullScreenIntent, Bitmap largeIcon) {
|
||||
Notification.Builder b = new Notification.Builder(context)
|
||||
.setWhen(n.when)
|
||||
.setSmallIcon(n.icon, n.iconLevel)
|
||||
.setContent(n.contentView)
|
||||
.setTicker(n.tickerText, tickerView)
|
||||
.setSound(n.sound, n.audioStreamType)
|
||||
.setVibrate(n.vibrate)
|
||||
.setLights(n.ledARGB, n.ledOnMS, n.ledOffMS)
|
||||
.setOngoing((n.flags & Notification.FLAG_ONGOING_EVENT) != 0)
|
||||
.setOnlyAlertOnce((n.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0)
|
||||
.setAutoCancel((n.flags & Notification.FLAG_AUTO_CANCEL) != 0)
|
||||
.setDefaults(n.defaults)
|
||||
.setContentTitle(contentTitle)
|
||||
.setContentText(contentText)
|
||||
.setContentInfo(contentInfo)
|
||||
.setContentIntent(contentIntent)
|
||||
.setDeleteIntent(n.deleteIntent)
|
||||
.setFullScreenIntent(fullScreenIntent,
|
||||
(n.flags & Notification.FLAG_HIGH_PRIORITY) != 0)
|
||||
.setLargeIcon(largeIcon)
|
||||
.setNumber(number);
|
||||
|
||||
return b.getNotification();
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,6 @@ import java.util.Date;
|
||||
import java.util.Properties;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
@@ -28,23 +27,26 @@ import android.content.res.AssetManager;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
import anroid.v4.compat.NotificationCompat;
|
||||
|
||||
/**
|
||||
* This is Twenty Codes, LLC Exception Handler of Awesomeness!
|
||||
* This class will be used to generate reports that will be emailed to us via the users email client after the users approval
|
||||
* This is Twenty Codes, LLC Exception Handler of Awesomeness! This class will
|
||||
* be used to generate reports that will be emailed to us via the users email
|
||||
* client after the users approval
|
||||
*
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public class ExceptionHandler implements UncaughtExceptionHandler, Runnable {
|
||||
|
||||
private static final String MSG_SUBJECT_TAG = "Exception Report";
|
||||
private static final String MSG_BODY = "Just click send to help make this application better. "+
|
||||
"No personal information is being sent (you can check by reading the rest of the email).";
|
||||
private static final String MSG_BODY = "Just click send to help make this application better. "
|
||||
+ "No personal information is being sent (you can check by reading the rest of the email).";
|
||||
protected static final int SIMPLE_NOTFICATION_ID = 45684645;
|
||||
private Thread.UncaughtExceptionHandler mDefaultUEH;
|
||||
private Activity mApp= null;
|
||||
private final Thread.UncaughtExceptionHandler mDefaultUEH;
|
||||
private Activity mApp = null;
|
||||
private Service mService = null;
|
||||
private BroadcastReceiver mBroadcastReceiver = null;
|
||||
private Context mContext;
|
||||
private final Context mContext;
|
||||
private Report mReport;
|
||||
private static final String TAG = "ExceptionHandler";
|
||||
private String mURL = null;
|
||||
@@ -54,61 +56,65 @@ public class ExceptionHandler implements UncaughtExceptionHandler, Runnable {
|
||||
|
||||
/**
|
||||
* Creates a new ExceptionHandler
|
||||
*
|
||||
* @param app
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public ExceptionHandler(Activity app) {
|
||||
this.mDefaultUEH = Thread.getDefaultUncaughtExceptionHandler();
|
||||
this.mApp = app;
|
||||
this.mContext = app;
|
||||
public ExceptionHandler(final Activity app) {
|
||||
mDefaultUEH = Thread.getDefaultUncaughtExceptionHandler();
|
||||
mApp = app;
|
||||
mContext = app;
|
||||
parseProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ExceptionHandler
|
||||
*
|
||||
* @param broadcastReceiver
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public ExceptionHandler(BroadcastReceiver broadcastReceiver, Context context){
|
||||
this.mDefaultUEH = Thread.getDefaultUncaughtExceptionHandler();
|
||||
this.mBroadcastReceiver = broadcastReceiver;
|
||||
this.mContext = context;
|
||||
public ExceptionHandler(final BroadcastReceiver broadcastReceiver, final Context context) {
|
||||
mDefaultUEH = Thread.getDefaultUncaughtExceptionHandler();
|
||||
mBroadcastReceiver = broadcastReceiver;
|
||||
mContext = context;
|
||||
parseProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ExceptionHandler
|
||||
*
|
||||
* @param service
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public ExceptionHandler(Service service){
|
||||
this.mDefaultUEH = Thread.getDefaultUncaughtExceptionHandler();
|
||||
this.mService = service;
|
||||
this.mContext = service;
|
||||
public ExceptionHandler(final Service service) {
|
||||
mDefaultUEH = Thread.getDefaultUncaughtExceptionHandler();
|
||||
mService = service;
|
||||
mContext = service;
|
||||
parseProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an email from the report
|
||||
*
|
||||
* @author ricky barrette
|
||||
*/
|
||||
private void displayEmailNotification(){
|
||||
private void displayEmailNotification() {
|
||||
Log.i(TAG, "displayEmailNotification");
|
||||
|
||||
CharSequence title = null;
|
||||
if(mApp != null)
|
||||
if (mApp != null)
|
||||
title = mApp.getTitle();
|
||||
|
||||
if(mService != null)
|
||||
if (mService != null)
|
||||
title = mService.getClass().getName();
|
||||
|
||||
if(mBroadcastReceiver != null)
|
||||
if (mBroadcastReceiver != null)
|
||||
title = mBroadcastReceiver.getClass().getName();
|
||||
|
||||
Intent intent = new Intent(Intent.ACTION_SEND);
|
||||
String theSubject = title + " " + MSG_SUBJECT_TAG;
|
||||
String theBody = "\n\n"+MSG_BODY+this.mReport.toString();
|
||||
intent.putExtra(Intent.EXTRA_EMAIL,new String[] {this.mEmail});
|
||||
final Intent intent = new Intent(Intent.ACTION_SEND);
|
||||
final String theSubject = title + " " + MSG_SUBJECT_TAG;
|
||||
final String theBody = "\n\n" + MSG_BODY + mReport.toString();
|
||||
intent.putExtra(Intent.EXTRA_EMAIL, new String[] { mEmail });
|
||||
intent.putExtra(Intent.EXTRA_TEXT, theBody);
|
||||
intent.putExtra(Intent.EXTRA_SUBJECT, theSubject);
|
||||
intent.setType("message/rfc822");
|
||||
@@ -117,114 +123,116 @@ public class ExceptionHandler implements UncaughtExceptionHandler, Runnable {
|
||||
}
|
||||
|
||||
/**
|
||||
* displays an notification in the status bar, letting the user know that there was an issue
|
||||
* displays an notification in the status bar, letting the user know that
|
||||
* there was an issue
|
||||
*
|
||||
* @param generatedReportIntent
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private void displayNotification(Intent generatedReportIntent) {
|
||||
private void displayNotification(final Intent generatedReportIntent) {
|
||||
Log.i(TAG, "displayNotification");
|
||||
Context context = mContext.getApplicationContext();
|
||||
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
Notification notifyDetails = new Notification(android.R.drawable.stat_notify_error, context.getString(R.string.sorry), System.currentTimeMillis());
|
||||
PendingIntent intent = PendingIntent.getActivity(context, 0, generatedReportIntent, android.content.Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
notifyDetails.setLatestEventInfo(context, context.getString(R.string.crash), context.getString(R.string.sorry), intent);
|
||||
notifyDetails.flags |= Notification.FLAG_AUTO_CANCEL;
|
||||
notificationManager.notify(SIMPLE_NOTFICATION_ID, notifyDetails);
|
||||
final Context context = mContext.getApplicationContext();
|
||||
final NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
final PendingIntent intent = PendingIntent.getActivity(context, 0, generatedReportIntent, android.content.Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
final NotificationCompat.Builder builder = new NotificationCompat.Builder(context).setContentTitle(context.getString(R.string.crash))
|
||||
.setContentText(context.getString(R.string.sorry)).setTicker(context.getString(R.string.crash)).setSmallIcon(android.R.drawable.stat_notify_error)
|
||||
.setWhen(System.currentTimeMillis()).setAutoCancel(true).setContentIntent(intent);
|
||||
notificationManager.notify(SIMPLE_NOTFICATION_ID, builder.getNotification());
|
||||
}
|
||||
|
||||
/**
|
||||
* parses in the exception handler options from the client application's assets folder. /assets/exceptionhandler.properties
|
||||
* parses in the exception handler options from the client application's
|
||||
* assets folder. /assets/exceptionhandler.properties
|
||||
*
|
||||
* @author ricky barrette
|
||||
*/
|
||||
private void parseProperties() {
|
||||
Resources resources = this.mContext.getResources();
|
||||
AssetManager assetManager = resources.getAssets();
|
||||
final Resources resources = mContext.getResources();
|
||||
final AssetManager assetManager = resources.getAssets();
|
||||
// Read from the /assets directory
|
||||
try {
|
||||
InputStream inputStream = assetManager.open("exceptionhandler.properties");
|
||||
Properties properties = new Properties();
|
||||
final InputStream inputStream = assetManager.open("exceptionhandler.properties");
|
||||
final Properties properties = new Properties();
|
||||
properties.load(inputStream);
|
||||
this.mURL = properties.getProperty("server");
|
||||
this.mEmail = properties.getProperty("email");
|
||||
this.mAppName = properties.getProperty("app");
|
||||
this.mTracker = properties.getProperty("tracker");
|
||||
} catch (IOException e) {
|
||||
mURL = properties.getProperty("server");
|
||||
mEmail = properties.getProperty("email");
|
||||
mAppName = properties.getProperty("app");
|
||||
mTracker = properties.getProperty("tracker");
|
||||
} catch (final IOException e) {
|
||||
Log.e(TAG, "Failed to open exceptionhandler.properties");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if(this.mEmail == null)
|
||||
displayNotification(new Intent(this.mContext, ExceptionReportActivity.class).putExtra("report", this.mReport));
|
||||
if (mEmail == null)
|
||||
displayNotification(new Intent(mContext, ExceptionReportActivity.class).putExtra("report", mReport));
|
||||
else
|
||||
displayEmailNotification();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when there is an uncaught exception.
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Thread.UncaughtExceptionHandler#uncaughtException(java.lang.Thread, java.lang.Throwable)
|
||||
* Called when there is an uncaught exception. (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Thread.UncaughtExceptionHandler#uncaughtException(java.lang.Thread,
|
||||
* java.lang.Throwable)
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
public void uncaughtException(Thread t, Throwable e) {
|
||||
public void uncaughtException(final Thread t, final Throwable e) {
|
||||
Log.d(TAG, "uncaughtException()");
|
||||
|
||||
// Log.d(TAG,"mURL = "+ this.mURL);
|
||||
// Log.d(TAG,"mEmail = "+ this.mEmail);
|
||||
// Log.d(TAG,"mURL = "+ this.mURL);
|
||||
// Log.d(TAG,"mEmail = "+ this.mEmail);
|
||||
|
||||
Date theDate = new Date();
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd_HH.mm.ss_zzz");
|
||||
PackageManager pm = mContext.getPackageManager();
|
||||
final Date theDate = new Date();
|
||||
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd_HH.mm.ss_zzz");
|
||||
final PackageManager pm = mContext.getPackageManager();
|
||||
|
||||
//app environment;
|
||||
// app environment;
|
||||
PackageInfo pi;
|
||||
try {
|
||||
pi = pm.getPackageInfo(mContext.getPackageName(), 0);
|
||||
} catch (NameNotFoundException eNnf) {
|
||||
//doubt this will ever run since we want info about our own package
|
||||
} catch (final NameNotFoundException eNnf) {
|
||||
// doubt this will ever run since we want info about our own package
|
||||
pi = new PackageInfo();
|
||||
pi.versionName = "unknown";
|
||||
pi.versionCode = 69;
|
||||
}
|
||||
|
||||
StringBuffer report = new StringBuffer();
|
||||
for (StackTraceElement item : e.getStackTrace())
|
||||
report.append("at "+item.toString() + "\n");
|
||||
final StringBuffer report = new StringBuffer();
|
||||
for (final StackTraceElement item : e.getStackTrace())
|
||||
report.append("at " + item.toString() + "\n");
|
||||
|
||||
StringBuffer causereport = new StringBuffer();
|
||||
Throwable cause = e.getCause();
|
||||
final StringBuffer causereport = new StringBuffer();
|
||||
final Throwable cause = e.getCause();
|
||||
if (cause != null) {
|
||||
causereport.append(cause.toString() + "\n \n");
|
||||
for (StackTraceElement item : cause.getStackTrace())
|
||||
causereport.append("at "+item.toString() + "\n");
|
||||
for (final StackTraceElement item : cause.getStackTrace())
|
||||
causereport.append("at " + item.toString() + "\n");
|
||||
}
|
||||
|
||||
//generate the report
|
||||
this.mReport = new Report(mURL).generateReport(e.toString(), report.toString(), causereport.toString(), sdf.format(theDate), Build.FINGERPRINT, pi.versionName+"b"+pi.versionCode, mAppName != null ? mAppName : mContext.getPackageName(), this.mTracker, mContext.getPackageName());
|
||||
// generate the report
|
||||
mReport = new Report(mURL).generateReport(e.toString(), report.toString(), causereport.toString(), sdf.format(theDate), Build.FINGERPRINT, pi.versionName + "b"
|
||||
+ pi.versionCode, mAppName != null ? mAppName : mContext.getPackageName(), mTracker, mContext.getPackageName());
|
||||
|
||||
//try to send file contents via email (need to do so via the UI thread)
|
||||
if(this.mApp != null){
|
||||
this.mApp.runOnUiThread(this);
|
||||
}
|
||||
// try to send file contents via email (need to do so via the UI thread)
|
||||
if (mApp != null)
|
||||
mApp.runOnUiThread(this);
|
||||
|
||||
|
||||
if(this.mService != null){
|
||||
if(this.mEmail == null)
|
||||
displayNotification(new Intent(this.mContext, ExceptionReportActivity.class).putExtra("report", this.mReport));
|
||||
if (mService != null)
|
||||
if (mEmail == null)
|
||||
displayNotification(new Intent(mContext, ExceptionReportActivity.class).putExtra("report", mReport));
|
||||
else
|
||||
displayEmailNotification();
|
||||
}
|
||||
|
||||
if(this.mBroadcastReceiver != null){
|
||||
if(this.mEmail == null)
|
||||
displayNotification(new Intent(this.mContext, ExceptionReportActivity.class).putExtra("report", this.mReport));
|
||||
if (mBroadcastReceiver != null)
|
||||
if (mEmail == null)
|
||||
displayNotification(new Intent(mContext, ExceptionReportActivity.class).putExtra("report", mReport));
|
||||
else
|
||||
displayEmailNotification();
|
||||
}
|
||||
|
||||
//do not forget to pass this exception through up the chain
|
||||
mDefaultUEH.uncaughtException(t,e);
|
||||
// do not forget to pass this exception through up the chain
|
||||
mDefaultUEH.uncaughtException(t, e);
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,9 @@ import android.widget.EditText;
|
||||
import android.widget.ListView;
|
||||
|
||||
/**
|
||||
* This activity will be used to present the user with the exception report, and allows them to send it, or not
|
||||
* This activity will be used to present the user with the exception report, and
|
||||
* allows them to send it, or not
|
||||
*
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public class ExceptionReportActivity extends Activity implements OnClickListener {
|
||||
@@ -26,37 +28,39 @@ public class ExceptionReportActivity extends Activity implements OnClickListener
|
||||
|
||||
/**
|
||||
* (non-Javadoc)
|
||||
* @see android.app.Activity#onCreate(android.os.Bundle)
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
Log.d(TAG, "onCreate()");
|
||||
super.onCreate(savedInstanceState);
|
||||
this.mReport = (Report) this.getIntent().getParcelableExtra("report");
|
||||
|
||||
if(this.getIntent().hasExtra("display"))
|
||||
this.setContentView(R.layout.list);
|
||||
else {
|
||||
this.setContentView(R.layout.exception_activity);
|
||||
this.findViewById(R.id.send).setOnClickListener(this);
|
||||
}
|
||||
ListView list = (ListView) this.findViewById(android.R.id.list);
|
||||
list.setAdapter(new ReportAdapter(this, this.mReport.getReport()));
|
||||
list.setClickable(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see android.view.View.OnClickListener#onClick(android.view.View)
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
EditText description = (EditText) findViewById(R.id.description);
|
||||
this.mReport.setDescription(description.getText().toString());
|
||||
public void onClick(final View v) {
|
||||
final EditText description = (EditText) findViewById(R.id.description);
|
||||
mReport.setDescription(description.getText().toString());
|
||||
v.setEnabled(false);
|
||||
this.startService(new Intent(this, ReportPostingService.class).putExtra("report", this.mReport));
|
||||
this.finish();
|
||||
startService(new Intent(this, ReportPostingService.class).putExtra("report", mReport));
|
||||
finish();
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see android.app.Activity#onCreate(android.os.Bundle)
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
protected void onCreate(final Bundle savedInstanceState) {
|
||||
Log.d(TAG, "onCreate()");
|
||||
super.onCreate(savedInstanceState);
|
||||
mReport = (Report) getIntent().getParcelableExtra("report");
|
||||
|
||||
if (getIntent().hasExtra("display"))
|
||||
this.setContentView(R.layout.list);
|
||||
else {
|
||||
this.setContentView(R.layout.exception_activity);
|
||||
findViewById(R.id.send).setOnClickListener(this);
|
||||
}
|
||||
final ListView list = (ListView) findViewById(android.R.id.list);
|
||||
list.setAdapter(new ReportAdapter(this, mReport.getReport()));
|
||||
list.setClickable(false);
|
||||
}
|
||||
}
|
||||
@@ -29,42 +29,48 @@ import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/**
|
||||
* This class will be used to generate a report, and insert it into our exception report database
|
||||
* This class will be used to generate a report, and insert it into our
|
||||
* exception report database
|
||||
*
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public class Report implements Parcelable{
|
||||
public class Report implements Parcelable {
|
||||
|
||||
private final String mUrl;
|
||||
private ArrayList<ReportItem> mReport;
|
||||
|
||||
public static final Parcelable.Creator<Report> CREATOR = new Parcelable.Creator<Report>() {
|
||||
public Report createFromParcel(Parcel in) {
|
||||
@Override
|
||||
public Report createFromParcel(final Parcel in) {
|
||||
return new Report(in);
|
||||
}
|
||||
|
||||
public Report[] newArray(int size) {
|
||||
@Override
|
||||
public Report[] newArray(final int size) {
|
||||
return new Report[size];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new Report
|
||||
*
|
||||
* @param in
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public Report(Parcel in){
|
||||
this.mUrl = in.readString();
|
||||
this.mReport = new ArrayList<ReportItem>();
|
||||
in.readTypedList(this.mReport, ReportItem.CREATOR);
|
||||
public Report(final Parcel in) {
|
||||
mUrl = in.readString();
|
||||
mReport = new ArrayList<ReportItem>();
|
||||
in.readTypedList(mReport, ReportItem.CREATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Report
|
||||
*
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public Report(String url) {
|
||||
// Log.d(TAG, url);
|
||||
this.mUrl = url;
|
||||
public Report(final String url) {
|
||||
// Log.d(TAG, url);
|
||||
mUrl = url;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -74,24 +80,25 @@ public class Report implements Parcelable{
|
||||
|
||||
/**
|
||||
* Files the report with the remote database
|
||||
*
|
||||
* @author ricky barrette
|
||||
* @throws IOException
|
||||
* @throws ClientProtocolException
|
||||
* @return String result
|
||||
*/
|
||||
public String file() throws ClientProtocolException, IOException{
|
||||
HttpClient httpclient = new DefaultHttpClient();
|
||||
HttpPost httppost = new HttpPost(mUrl);
|
||||
public String file() throws ClientProtocolException, IOException {
|
||||
final HttpClient httpclient = new DefaultHttpClient();
|
||||
final HttpPost httppost = new HttpPost(mUrl);
|
||||
httppost.setEntity(new UrlEncodedFormEntity(getNameValuePairs()));
|
||||
//return the results
|
||||
HttpResponse response = httpclient.execute(httppost);
|
||||
HttpEntity entity = response.getEntity();
|
||||
InputStream is = entity.getContent();
|
||||
// return the results
|
||||
final HttpResponse response = httpclient.execute(httppost);
|
||||
final HttpEntity entity = response.getEntity();
|
||||
final InputStream is = entity.getContent();
|
||||
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
final BufferedReader reader = new BufferedReader(new InputStreamReader(is, "iso-8859-1"), 8);
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append(reader.readLine() + "\n");
|
||||
String line="0";
|
||||
String line = "0";
|
||||
while ((line = reader.readLine()) != null)
|
||||
sb.append(line + "\n");
|
||||
is.close();
|
||||
@@ -101,24 +108,26 @@ public class Report implements Parcelable{
|
||||
|
||||
/**
|
||||
* Generates a report to be displayed form a downloaded JSON object
|
||||
*
|
||||
* @param report
|
||||
* @return
|
||||
* @author ricky barrette
|
||||
* @throws JSONException
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public Report generateReport(JSONObject report) throws JSONException{
|
||||
this.mReport = new ArrayList<ReportItem>();
|
||||
Iterator iter = report.keys();
|
||||
while(iter.hasNext()){
|
||||
String key = (String)iter.next();
|
||||
this.mReport.add(new ReportItem(key , report.getString(key)));
|
||||
public Report generateReport(final JSONObject report) throws JSONException {
|
||||
mReport = new ArrayList<ReportItem>();
|
||||
final Iterator iter = report.keys();
|
||||
while (iter.hasNext()) {
|
||||
final String key = (String) iter.next();
|
||||
mReport.add(new ReportItem(key, report.getString(key)));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a report to be sent.
|
||||
*
|
||||
* @param msg
|
||||
* @param stackTrace
|
||||
* @param cause
|
||||
@@ -128,29 +137,31 @@ public class Report implements Parcelable{
|
||||
* @return this
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public Report generateReport(String msg, String stackTrace, String cause, String date, String device, String appVersion, String app, String tracker, String packageName){
|
||||
this.mReport = new ArrayList<ReportItem>();
|
||||
this.mReport.add(new ReportItem("app",app));
|
||||
this.mReport.add(new ReportItem("version",appVersion));
|
||||
this.mReport.add(new ReportItem("date",date));
|
||||
this.mReport.add(new ReportItem("msg",msg));
|
||||
this.mReport.add(new ReportItem("stackTrace",stackTrace));
|
||||
this.mReport.add(new ReportItem("cause",cause));
|
||||
this.mReport.add(new ReportItem("device",device));
|
||||
this.mReport.add(new ReportItem("tracker",tracker));
|
||||
this.mReport.add(new ReportItem("package",packageName));
|
||||
public Report generateReport(final String msg, final String stackTrace, final String cause, final String date, final String device, final String appVersion,
|
||||
final String app, final String tracker, final String packageName) {
|
||||
mReport = new ArrayList<ReportItem>();
|
||||
mReport.add(new ReportItem("app", app));
|
||||
mReport.add(new ReportItem("version", appVersion));
|
||||
mReport.add(new ReportItem("date", date));
|
||||
mReport.add(new ReportItem("msg", msg));
|
||||
mReport.add(new ReportItem("stackTrace", stackTrace));
|
||||
mReport.add(new ReportItem("cause", cause));
|
||||
mReport.add(new ReportItem("device", device));
|
||||
mReport.add(new ReportItem("tracker", tracker));
|
||||
mReport.add(new ReportItem("package", packageName));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the name value pairs from the report bundle
|
||||
*
|
||||
* @return
|
||||
* @author ricky barrette
|
||||
*/
|
||||
private ArrayList<NameValuePair> getNameValuePairs() {
|
||||
ArrayList<NameValuePair> list = new ArrayList<NameValuePair>();
|
||||
for(ReportItem entry : this.mReport)
|
||||
list.add(new BasicNameValuePair(entry.getKey(), (String) entry.getValue()));
|
||||
final ArrayList<NameValuePair> list = new ArrayList<NameValuePair>();
|
||||
for (final ReportItem entry : mReport)
|
||||
list.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
|
||||
return list;
|
||||
}
|
||||
|
||||
@@ -158,17 +169,18 @@ public class Report implements Parcelable{
|
||||
* @return the generated exception report
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public ArrayList<NameValuePair> getReport(){
|
||||
public ArrayList<NameValuePair> getReport() {
|
||||
return getNameValuePairs();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the optional users description of what happened
|
||||
*
|
||||
* @param string
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public Report setDescription(String description) {
|
||||
this.mReport.add(new ReportItem("description", description));
|
||||
public Report setDescription(final String description) {
|
||||
mReport.add(new ReportItem("description", description));
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -177,18 +189,18 @@ public class Report implements Parcelable{
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
public String toString(){
|
||||
StringBuilder s = new StringBuilder();
|
||||
for(ReportItem item : this.mReport){
|
||||
s.append("\n\n-----"+ item.getKey()+"-----");
|
||||
s.append("\n"+item.getValue());
|
||||
public String toString() {
|
||||
final StringBuilder s = new StringBuilder();
|
||||
for (final ReportItem item : mReport) {
|
||||
s.append("\n\n-----" + item.getKey() + "-----");
|
||||
s.append("\n" + item.getValue());
|
||||
}
|
||||
return s.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
out.writeString(this.mUrl);
|
||||
out.writeTypedList(this.mReport);
|
||||
public void writeToParcel(final Parcel out, final int flags) {
|
||||
out.writeString(mUrl);
|
||||
out.writeTypedList(mReport);
|
||||
}
|
||||
}
|
||||
@@ -17,55 +17,65 @@ import android.view.ViewGroup;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.TwentyCodes.android.exception.R;
|
||||
|
||||
/**
|
||||
* This class will be used to populate a custom Listview used to display the Generated exception report
|
||||
* This class will be used to populate a custom Listview used to display the
|
||||
* Generated exception report
|
||||
*
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public class ReportAdapter extends BaseAdapter {
|
||||
|
||||
private ArrayList<NameValuePair> mReport;
|
||||
private LayoutInflater mInflater;
|
||||
class ViewHolder {
|
||||
TextView title;
|
||||
TextView body;
|
||||
}
|
||||
|
||||
private final ArrayList<NameValuePair> mReport;
|
||||
|
||||
private final LayoutInflater mInflater;
|
||||
|
||||
/**
|
||||
* Creates a new ReportAdapter
|
||||
*
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public ReportAdapter(Context context, ArrayList<NameValuePair> report) {
|
||||
public ReportAdapter(final Context context, final ArrayList<NameValuePair> report) {
|
||||
super();
|
||||
// Cache the LayoutInflate to avoid asking for a new one each time.
|
||||
this.mInflater = LayoutInflater.from(context);
|
||||
this.mReport = report;
|
||||
mInflater = LayoutInflater.from(context);
|
||||
mReport = report;
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see android.widget.Adapter#getCount()
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
public int getCount() {
|
||||
return this.mReport.size();
|
||||
return mReport.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see android.widget.Adapter#getItem(int)
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
public NameValuePair getItem(int index) {
|
||||
return this.mReport.get(index);
|
||||
public NameValuePair getItem(final int index) {
|
||||
return mReport.get(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see android.widget.Adapter#getItemId(int)
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
public long getItemId(int index) {
|
||||
public long getItemId(final int index) {
|
||||
return index;
|
||||
}
|
||||
|
||||
@@ -73,27 +83,30 @@ public class ReportAdapter extends BaseAdapter {
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public View getView(final int position, View convertView, ViewGroup parent) {
|
||||
public View getView(final int position, View convertView, final ViewGroup parent) {
|
||||
|
||||
// A ViewHolder keeps references to children views to avoid unnecessary calls to findViewById() on each row.
|
||||
// A ViewHolder keeps references to children views to avoid unnecessary
|
||||
// calls to findViewById() on each row.
|
||||
ViewHolder holder;
|
||||
|
||||
// When convertView is not null, we can reuse it directly, there is no need
|
||||
// to reinflate it. We only inflate a new View when the convertView supplied
|
||||
// When convertView is not null, we can reuse it directly, there is no
|
||||
// need
|
||||
// to reinflate it. We only inflate a new View when the convertView
|
||||
// supplied
|
||||
// by ListView is null.
|
||||
if (convertView == null) {
|
||||
convertView = mInflater.inflate(R.layout.exception_list_item, null);
|
||||
|
||||
// Creates a ViewHolder and store references to the two children views
|
||||
// Creates a ViewHolder and store references to the two children
|
||||
// views
|
||||
// we want to bind data to.
|
||||
holder = new ViewHolder();
|
||||
holder.title = (TextView) convertView.findViewById(R.id.exception_title);
|
||||
holder.body = (TextView) convertView.findViewById(R.id.exception_text);
|
||||
|
||||
convertView.setTag(holder);
|
||||
} else {
|
||||
} else
|
||||
holder = (ViewHolder) convertView.getTag();
|
||||
}
|
||||
|
||||
/*
|
||||
* Bind the data efficiently with the holder.
|
||||
@@ -104,9 +117,4 @@ public class ReportAdapter extends BaseAdapter {
|
||||
return convertView;
|
||||
}
|
||||
|
||||
class ViewHolder {
|
||||
TextView title;
|
||||
TextView body;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,18 +10,22 @@ import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/**
|
||||
* This class will represent an individual report item. The ReportItems will be used in an array list that will be passed via intent.
|
||||
* This will allow for our report items to stay in the proper order.
|
||||
* This class will represent an individual report item. The ReportItems will be
|
||||
* used in an array list that will be passed via intent. This will allow for our
|
||||
* report items to stay in the proper order.
|
||||
*
|
||||
* @author ricky
|
||||
*/
|
||||
public final class ReportItem implements Parcelable {
|
||||
|
||||
public static final Parcelable.Creator<ReportItem> CREATOR = new Parcelable.Creator<ReportItem>() {
|
||||
public ReportItem createFromParcel(Parcel in) {
|
||||
@Override
|
||||
public ReportItem createFromParcel(final Parcel in) {
|
||||
return new ReportItem(in);
|
||||
}
|
||||
|
||||
public ReportItem[] newArray(int size) {
|
||||
@Override
|
||||
public ReportItem[] newArray(final int size) {
|
||||
return new ReportItem[size];
|
||||
}
|
||||
};
|
||||
@@ -30,24 +34,28 @@ public final class ReportItem implements Parcelable {
|
||||
private final String mValue;
|
||||
|
||||
/**
|
||||
* Creates a new ReportItem
|
||||
* @author ricky barrette
|
||||
* Creates a new ReportItem from a parcel
|
||||
*
|
||||
* @param in
|
||||
*/
|
||||
public ReportItem(String key, String value) {
|
||||
this.mKey = key;
|
||||
this.mValue = value;
|
||||
public ReportItem(final Parcel in) {
|
||||
mKey = in.readString();
|
||||
mValue = in.readString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ReportItem from a parcel
|
||||
* @param in
|
||||
* Creates a new ReportItem
|
||||
*
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public ReportItem(Parcel in){
|
||||
this.mKey = in.readString();
|
||||
this.mValue = in.readString();
|
||||
public ReportItem(final String key, final String value) {
|
||||
mKey = key;
|
||||
mValue = value;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see android.os.Parcelable#describeContents()
|
||||
*/
|
||||
@Override
|
||||
@@ -56,27 +64,29 @@ public final class ReportItem implements Parcelable {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see android.os.Parcelable#writeToParcel(android.os.Parcel, int)
|
||||
*/
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(this.mKey);
|
||||
dest.writeString(this.mValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the key
|
||||
*/
|
||||
public String getKey() {
|
||||
return this.mKey;
|
||||
return mKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the value
|
||||
*/
|
||||
public String getValue() {
|
||||
return this.mValue;
|
||||
return mValue;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see android.os.Parcelable#writeToParcel(android.os.Parcel, int)
|
||||
*/
|
||||
@Override
|
||||
public void writeToParcel(final Parcel dest, final int flags) {
|
||||
dest.writeString(mKey);
|
||||
dest.writeString(mValue);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -10,9 +10,7 @@ import java.io.IOException;
|
||||
|
||||
import org.apache.http.client.ClientProtocolException;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Notification;
|
||||
import android.app.Notification.Builder;
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
@@ -20,10 +18,12 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
import android.util.Log;
|
||||
import anroid.v4.compat.NotificationCompat;
|
||||
|
||||
/**
|
||||
* This service will allow the exception handler to post reports in the backgound,
|
||||
* allowing the user to do what ever they want
|
||||
* This service will allow the exception handler to post reports in the
|
||||
* backgound, allowing the user to do what ever they want
|
||||
*
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public class ReportPostingService extends Service {
|
||||
@@ -39,6 +39,7 @@ public class ReportPostingService extends Service {
|
||||
|
||||
/**
|
||||
* Fires of a notification based upon api level
|
||||
*
|
||||
* @param title
|
||||
* @param contentText
|
||||
* @param ticker
|
||||
@@ -47,105 +48,83 @@ public class ReportPostingService extends Service {
|
||||
* @param isOngoing
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@SuppressLint("NewApi")
|
||||
@SuppressWarnings("deprecation")
|
||||
private void fireNotification(String title, String contentText, String ticker, int icon, Intent intent, boolean isOngoing) {
|
||||
private void fireNotification(final String title, final String contentText, final String ticker, final int icon, final Intent intent, final boolean isOngoing) {
|
||||
PendingIntent pendingIntent = null;
|
||||
if(intent != null)
|
||||
pendingIntent = PendingIntent.getService(this.getApplicationContext(), 0, intent, 0);
|
||||
/*
|
||||
* Use the appropriate notificafation methods
|
||||
*/
|
||||
if(Integer.valueOf(android.os.Build.VERSION.SDK_INT) > 11){
|
||||
Builder builder = new Notification.Builder(this.getApplicationContext())
|
||||
.setContentTitle(title)
|
||||
.setContentText(contentText)
|
||||
.setTicker(ticker)
|
||||
.setSmallIcon(icon)
|
||||
.setWhen(System.currentTimeMillis());
|
||||
if(isOngoing)
|
||||
if (intent != null)
|
||||
pendingIntent = PendingIntent.getService(getApplicationContext(), 0, intent, 0);
|
||||
|
||||
final NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext()).setContentTitle(title).setContentText(contentText)
|
||||
.setTicker(ticker).setSmallIcon(icon).setWhen(System.currentTimeMillis());
|
||||
|
||||
if (isOngoing)
|
||||
builder.setOngoing(true);
|
||||
else
|
||||
builder.setAutoCancel(true);
|
||||
|
||||
if (intent != null)
|
||||
builder.setContentIntent(pendingIntent);
|
||||
mNotificationManager.notify(NOTIFICATION_ID, builder.getNotification());
|
||||
} else {
|
||||
Notification notification = new Notification(icon, title , System.currentTimeMillis());
|
||||
if(isOngoing)
|
||||
notification.flags |= Notification.FLAG_ONGOING_EVENT;
|
||||
else
|
||||
notification.flags |= Notification.FLAG_AUTO_CANCEL;
|
||||
notification.setLatestEventInfo(this.getApplicationContext(), title, contentText, pendingIntent);
|
||||
mNotificationManager.notify(NOTIFICATION_ID, notification);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the report object from the intent
|
||||
*
|
||||
* @param intent
|
||||
* @author ricky barrette
|
||||
*/
|
||||
private void getReport(Intent intent) {
|
||||
private void getReport(final Intent intent) {
|
||||
mReport = (Report) intent.getParcelableExtra("report");
|
||||
}
|
||||
|
||||
/**
|
||||
* notifiys the user that we are sending a report
|
||||
*
|
||||
* @author ricky barrette
|
||||
*/
|
||||
private void notifyError() {
|
||||
fireNotification(getString(R.string.reporting_error),
|
||||
getString(R.string.reporting_error_msg),
|
||||
getString(R.string.reporting_error_msg),
|
||||
android.R.drawable.stat_notify_error,
|
||||
new Intent(this.getApplicationContext(), ReportPostingService.class).putExtras(mIntent),
|
||||
false);
|
||||
fireNotification(getString(R.string.reporting_error), getString(R.string.reporting_error_msg), getString(R.string.reporting_error_msg),
|
||||
android.R.drawable.stat_notify_error, new Intent(getApplicationContext(), ReportPostingService.class).putExtras(mIntent), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* notifiys the user that we are sending a report
|
||||
*
|
||||
* @author ricky barrette
|
||||
*/
|
||||
private void notifySending() {
|
||||
fireNotification(getString(R.string.sending),
|
||||
getString(R.string.sending_report),
|
||||
getString(R.string.sending),
|
||||
android.R.drawable.stat_sys_upload,
|
||||
null,
|
||||
true);
|
||||
|
||||
fireNotification(getString(R.string.sending), getString(R.string.sending_report), getString(R.string.sending), android.R.drawable.stat_sys_upload, null, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see android.app.Service#onBind(android.content.Intent)
|
||||
*/
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
public IBinder onBind(final Intent intent) {
|
||||
// Unused
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the service is being created
|
||||
* Here we want to display a notifcation,
|
||||
* to inform the user what we are doing.
|
||||
* (non-Javadoc)
|
||||
* Called when the service is being created Here we want to display a
|
||||
* notifcation, to inform the user what we are doing. (non-Javadoc)
|
||||
*
|
||||
* @see android.app.Service#onCreate()
|
||||
*/
|
||||
@Override
|
||||
public void onCreate() {
|
||||
Context context = this.getApplicationContext();
|
||||
final Context context = getApplicationContext();
|
||||
mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
|
||||
notifySending();
|
||||
super.onCreate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the service is being destroyed
|
||||
* Here we want to dismiss the notifications
|
||||
* (non-Javadoc)
|
||||
* Called when the service is being destroyed Here we want to dismiss the
|
||||
* notifications (non-Javadoc)
|
||||
*
|
||||
* @see android.app.Service#onDestroy()
|
||||
*/
|
||||
@Override
|
||||
@@ -158,11 +137,12 @@ public class ReportPostingService extends Service {
|
||||
|
||||
/**
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see android.app.Service#onStart(android.content.Intent, int)
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public void onStart(Intent intent, int startId) {
|
||||
public void onStart(final Intent intent, final int startId) {
|
||||
mStartId = startId;
|
||||
getReport(intent);
|
||||
postReport();
|
||||
@@ -172,10 +152,12 @@ public class ReportPostingService extends Service {
|
||||
|
||||
/**
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see android.app.Service#onStartCommand(android.content.Intent, int, int)
|
||||
*/
|
||||
@TargetApi(5)
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
public int onStartCommand(final Intent intent, final int flags, final int startId) {
|
||||
mStartId = startId;
|
||||
getReport(intent);
|
||||
postReport();
|
||||
@@ -185,22 +167,28 @@ public class ReportPostingService extends Service {
|
||||
|
||||
/**
|
||||
* Posts a copy of the report to the report handing server
|
||||
*
|
||||
* @author ricky barrette
|
||||
*/
|
||||
private void postReport(){
|
||||
if(!isStarted){
|
||||
private void postReport() {
|
||||
if (!isStarted) {
|
||||
isStarted = true;
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Log.d(TAG, mReport.file());
|
||||
} catch (ClientProtocolException e) {
|
||||
} catch (final ClientProtocolException e) {
|
||||
e.printStackTrace();
|
||||
hasErrored = true;
|
||||
} catch (IOException e) {
|
||||
} catch (final IOException e) {
|
||||
e.printStackTrace();
|
||||
hasErrored = true;
|
||||
} finally {
|
||||
ReportPostingService.this.stopSelf(mStartId);
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,91 +15,96 @@ import android.util.AttributeSet;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewGroup.LayoutParams;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
/**
|
||||
* this class will be a simple preference that contains only a text view that will display the application build information
|
||||
* this class will be a simple preference that contains only a text view that
|
||||
* will display the application build information
|
||||
*
|
||||
* @author ricky barrette
|
||||
*/
|
||||
public class VersionInformationPreference extends Preference {
|
||||
|
||||
private Context mContext;
|
||||
|
||||
private final Context mContext;
|
||||
|
||||
/**
|
||||
* creates a preference that is nothing but a text view
|
||||
*
|
||||
* @param context
|
||||
*/
|
||||
public VersionInformationPreference(Context context) {
|
||||
public VersionInformationPreference(final Context context) {
|
||||
super(context);
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* creates a preference that is nothing but a text view
|
||||
*
|
||||
* @param context
|
||||
* @param attrs
|
||||
*/
|
||||
public VersionInformationPreference(Context context, AttributeSet attrs) {
|
||||
public VersionInformationPreference(final Context context, final AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* creates a preference that is nothing but a text view
|
||||
*
|
||||
* @param context
|
||||
* @param attrs
|
||||
* @param defStyle
|
||||
*/
|
||||
public VersionInformationPreference(Context context, AttributeSet attrs, int defStyle) {
|
||||
public VersionInformationPreference(final Context context, final AttributeSet attrs, final int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* creates a linear layout the contains only a textview.
|
||||
* (non-Javadoc)
|
||||
* creates a linear layout the contains only a textview. (non-Javadoc)
|
||||
*
|
||||
* @see android.preference.Preference#onCreateView(android.view.ViewGroup)
|
||||
* @param parent
|
||||
* @return
|
||||
* @author ricky barrette
|
||||
*/
|
||||
@Override
|
||||
protected View onCreateView(ViewGroup parent){
|
||||
protected View onCreateView(final ViewGroup parent) {
|
||||
|
||||
/*
|
||||
* get the build information, and build the string
|
||||
*/
|
||||
PackageManager pm = mContext.getPackageManager();
|
||||
final PackageManager pm = mContext.getPackageManager();
|
||||
PackageInfo pi;
|
||||
try {
|
||||
pi = pm.getPackageInfo(mContext.getPackageName(), 0);
|
||||
} catch (NameNotFoundException eNnf) {
|
||||
//doubt this will ever run since we want info about our own package
|
||||
} catch (final NameNotFoundException eNnf) {
|
||||
// doubt this will ever run since we want info about our own package
|
||||
pi = new PackageInfo();
|
||||
pi.versionName = "unknown";
|
||||
pi.versionCode = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* create a vertical linear layout that width and height that wraps content
|
||||
* create a vertical linear layout that width and height that wraps
|
||||
* content
|
||||
*/
|
||||
LinearLayout layout = new LinearLayout(getContext());
|
||||
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
|
||||
// params.gravity = Gravity.CENTER;
|
||||
final LinearLayout layout = new LinearLayout(getContext());
|
||||
final LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
|
||||
// params.gravity = Gravity.CENTER;
|
||||
layout.setPadding(15, 5, 10, 5);
|
||||
layout.setOrientation(LinearLayout.VERTICAL);
|
||||
|
||||
layout.removeAllViews();
|
||||
|
||||
/*
|
||||
* create a textview that will be used to display the application's name and build information
|
||||
* and add it to the layout
|
||||
* create a textview that will be used to display the application's name
|
||||
* and build information and add it to the layout
|
||||
*/
|
||||
TextView title = new TextView(getContext());
|
||||
title.setText(mContext.getString(R.string.version)+" "+pi.versionName+" bulid "+pi.versionCode);
|
||||
final TextView title = new TextView(getContext());
|
||||
title.setText(mContext.getString(R.string.version) + " " + pi.versionName + " bulid " + pi.versionCode);
|
||||
title.setTextSize(16);
|
||||
title.setTypeface(Typeface.SANS_SERIF);
|
||||
title.setGravity(Gravity.LEFT);
|
||||
|
||||
Reference in New Issue
Block a user