I'm using azure sdk for android and follow the tutorial https://azure.microsoft.com/en-us/documentation/articles/mobile-services-dotnet-backend-android-get-started-data/.
When I'm trying to connect and insert data to mobile service table all is ok, but when I query the table in activity my app gets stuck, though there are only several entries in the table and execute method successfully returns Future.
public static MobileServiceClient mClient;
public static void connect(Context context) {
try {
mClient = new MobileServiceClient(storageLink, key, context);
} catch (MalformedURLException e) {
Log.e("AzureService.connect", "Storage access failed" + storageLink);
}
}
public static InstallationData get(final String deviceId) {
MobileServiceTable<InstallationData> table= mClient.getTable(InstallationData.class);
final MobileServiceList<InstallationData> result;
try {
result = table.where().field("deviceid").eq(deviceId).execute().get();
for (InstallationData item : result) {
return item;
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
return null;
}
public static void store(final InstallationData item) {
mClient.getTable(InstallationData.class).insert(item, new TableOperationCallback<InstallationData>() {
public void onCompleted(InstallationData entity, Exception exception, ServiceFilterResponse response) {
if (exception == null) {
Log.d("AzureService.store()", "Data about " + item.getDeviceid() + "" + "is successfully updated");
} else {
exception.printStackTrace();
Log.e("AzureService.store()", "Data about " + item.getDeviceid() + "" + "is failed to update");
}
}
});
}
Thank you in advance!
I'm about to do some refactoring off my app and I came to think about this simple yet complex topic, logging, how can it be so hard to do clean, effective and informative logging...
When you read documentation on logging you often see this snippet
if (BuildConfig.DEBUG) {
Log.d(TAG + "message");
}
and it makes me wonder what the purpose is with it? According to the documentation, Android Developer - Log, the debug log messages are compiled in but stripped at runtime, so you wouldn't need to have the log call within that if statement. Or am I missunderstanding anything?
Then I'm also kind of wondering what the real benefit is with using any other Log.x() calls except debug as the log entries will not be seen by the user or logged into some errorfile, so they will be compiled in and executed in the production environment for no purpose at all? This is maybe a use case for the if statement before?
I mentioned earlier that the log entry isn't logged into a file. Why isn't this a built in feature in Android? Is it because of performance issues, unnecessary permission usage or something else? I have implemented this functionality in my own logging class, but now I wonder if it's bad practice? But it's also nice to have logs with important log entries?
So to wrap it up, to implement clean, effective and informative logging, both during development and in production. What's the best practices?
Logs only needed to debug applications during development, to ensure that the feature works as expected and produces desired results. The best practice is, I believe, to do logging in any way which is most convenient to you and allows to find and resolve issues as quickly and efficiently as possible
I mentioned earlier that the log entry isn't logged into a file. Why
isn't this a built in feature in Android?
Who (except a programmer on the development stage) would want an application to waste limited storage space on one's device with useless data? Users don't see, don't read, don't use logs. They don't need this garbage. Application in production must not produce any logs and, of course, must not save them to files.
The only logging which should be implemented in released application is unhandled exceptions logging. Moreover, it's application's responsibility to handle these logs if it suggests sending crash reports, and removing them after the report has been sent.
Another reason logs should not be created by released apps is that they may contain sensitive data and output which requires user authorization, thus introducing security flaws.
I believe the best practice is to remove all logs as soon as the module or feature is fully implemented and thoroughly tested, before deployment to production. Introducing if (BuildConfig.DEBUG) condition helps to ensure this has been achieved.
This will generate clean debug tags with this format ClasssName[MethodName] - LineNumber with reflection.
Complete code with inline comments is available as a gist here.
import android.util.Log;
public class Logger {
public enum LOGGER_DEPTH {
ACTUAL_METHOD(4),
LOGGER_METHOD(3),
STACK_TRACE_METHOD(1),
JVM_METHOD(0);
private final int value;
private LOGGER_DEPTH(final int newValue) {
value = newValue;
}
public int getValue() {
return value;
}
}
private static final String personalTAG = "Logger";
private StringBuilder sb;
private Logger() {
if (LoggerLoader.instance != null) {
Log.e(personalTAG, "Error: Logger already instantiated");
throw new IllegalStateException("Already Instantiated");
} else {
this.sb = new StringBuilder(255);
}
}
public static Logger getLogger() {
return LoggerLoader.instance;
}
private String getTag(LOGGER_DEPTH depth) {
try {
String className = Thread.currentThread().getStackTrace()[depth.getValue()].getClassName();
sb.append(className.substring(className.lastIndexOf(".") + 1));
sb.append("[");
sb.append(Thread.currentThread().getStackTrace()[depth.getValue()].getMethodName());
sb.append("] - ");
sb.append(Thread.currentThread().getStackTrace()[depth.getValue()].getLineNumber());
return sb.toString();
} catch (Exception ex) {
ex.printStackTrace();
Log.d(personalTAG, ex.getMessage());
} finally {
sb.setLength(0);
}
return null;
}
public void d(String msg) {
try {
Log.d(getTag(LOGGER_DEPTH.ACTUAL_METHOD), msg);
} catch (Exception exception) {
Log.e(getTag(LOGGER_DEPTH.ACTUAL_METHOD), "Logger failed, exception: " + exception.getMessage());
}
}
public void d(String msg, LOGGER_DEPTH depth) {
try {
Log.d(getTag(depth), msg);
} catch (Exception exception) {
Log.e(getTag(LOGGER_DEPTH.ACTUAL_METHOD), "Logger failed, exception: " + exception.getMessage());
}
}
public void d(String msg, Throwable t, LOGGER_DEPTH depth) {
try {
Log.d(getTag(depth), msg, t);
} catch (Exception exception) {
Log.e(getTag(LOGGER_DEPTH.ACTUAL_METHOD), "Logger failed, exception: " + exception.getMessage());
}
}
public void e(String msg) {
try {
Log.e(getTag(LOGGER_DEPTH.ACTUAL_METHOD), msg);
} catch (Exception exception) {
Log.e(getTag(LOGGER_DEPTH.ACTUAL_METHOD), "Logger failed, exception: " + exception.getMessage());
}
}
public void e(String msg, LOGGER_DEPTH depth) {
try {
Log.e(getTag(depth), msg);
} catch (Exception exception) {
Log.e(getTag(LOGGER_DEPTH.ACTUAL_METHOD), "Logger failed, exception: " + exception.getMessage());
}
}
public void e(String msg, Throwable t, LOGGER_DEPTH depth) {
try {
Log.e(getTag(depth), msg, t);
} catch (Exception exception) {
Log.e(getTag(LOGGER_DEPTH.ACTUAL_METHOD), "Logger failed, exception: " + exception.getMessage());
}
}
public void w(String msg) {
try {
Log.w(getTag(LOGGER_DEPTH.ACTUAL_METHOD), msg);
} catch (Exception exception) {
Log.e(getTag(LOGGER_DEPTH.ACTUAL_METHOD), "Logger failed, exception: " + exception.getMessage());
}
}
public void w(String msg, LOGGER_DEPTH depth) {
try {
Log.w(getTag(depth), msg);
} catch (Exception exception) {
Log.e(getTag(LOGGER_DEPTH.ACTUAL_METHOD), "Logger failed, exception: " + exception.getMessage());
}
}
public void w(String msg, Throwable t, LOGGER_DEPTH depth) {
try {
Log.w(getTag(depth), msg, t);
} catch (Exception exception) {
Log.e(getTag(LOGGER_DEPTH.ACTUAL_METHOD), "Logger failed, exception: " + exception.getMessage());
}
}
public void v(String msg) {
try {
Log.v(getTag(LOGGER_DEPTH.ACTUAL_METHOD), msg);
} catch (Exception exception) {
Log.e(getTag(LOGGER_DEPTH.ACTUAL_METHOD), "Logger failed, exception: " + exception.getMessage());
}
}
public void v(String msg, LOGGER_DEPTH depth) {
try {
Log.v(getTag(depth), msg);
} catch (Exception exception) {
Log.e(getTag(LOGGER_DEPTH.ACTUAL_METHOD), "Logger failed, exception: " + exception.getMessage());
}
}
public void v(String msg, Throwable t, LOGGER_DEPTH depth) {
try {
Log.v(getTag(depth), msg, t);
} catch (Exception exception) {
Log.e(getTag(LOGGER_DEPTH.ACTUAL_METHOD), "Logger failed, exception: " + exception.getMessage());
}
}
public void i(String msg) {
try {
Log.i(getTag(LOGGER_DEPTH.ACTUAL_METHOD), msg);
} catch (Exception exception) {
Log.e(getTag(LOGGER_DEPTH.ACTUAL_METHOD), "Logger failed, exception: " + exception.getMessage());
}
}
public void i(String msg, LOGGER_DEPTH depth) {
try {
Log.i(getTag(depth), msg);
} catch (Exception exception) {
Log.e(getTag(LOGGER_DEPTH.ACTUAL_METHOD), "Logger failed, exception: " + exception.getMessage());
}
}
public void i(String msg, Throwable t, LOGGER_DEPTH depth) {
try {
Log.i(getTag(depth), msg, t);
} catch (Exception exception) {
Log.e(getTag(LOGGER_DEPTH.ACTUAL_METHOD), "Logger failed, exception: " + exception.getMessage());
}
}
public void wtf(String msg) {
try {
Log.wtf(getTag(LOGGER_DEPTH.ACTUAL_METHOD), msg);
} catch (Exception exception) {
Log.e(getTag(LOGGER_DEPTH.ACTUAL_METHOD), "Logger failed, exception: " + exception.getMessage());
}
}
public void wtf(String msg, LOGGER_DEPTH depth) {
try {
Log.wtf(getTag(depth), msg);
} catch (Exception exception) {
Log.e(getTag(LOGGER_DEPTH.ACTUAL_METHOD), "Logger failed, exception: " + exception.getMessage());
}
}
public void wtf(String msg, Throwable t, LOGGER_DEPTH depth) {
try {
Log.wtf(getTag(depth), msg, t);
} catch (Exception exception) {
Log.e(getTag(LOGGER_DEPTH.ACTUAL_METHOD), "Logger failed, exception: " + exception.getMessage());
}
}
private static class LoggerLoader {
private static final Logger instance = new Logger();
}
}
I've stumbled with that very same problem since I started working in Android and I have created this open source project(Android Studio Macros) that allows you to do what you want plus some more complicated things by using "//<#DEBUG_AREA> and //<#/DEBUG_AREA>" tags within your code, the basic idea is that anything within those tags will be commented when you change your build variants for example if you have something like this in a for loop:
//=========This piece of code is only for logging purposes...=========
Log.e("LogUserInfo", "Name: " + name);
Log.e("LogUserInfo", "Id: " + user.getId());
Log.e("LogUserInfo", "Id: " + user.getDistance());
//====================================================================
In stead of doing this:
if(DEBUG){
Log.e("LogginUserInfo", "Name: " + name);
Log.e("LogginUserInfo", "Id: " + user.getId());
Log.e("LogginUserInfo", "Id: " + user.getDistance());
}
With this macro you can do this(full method):
private List<String> getNamesOfUsersNearMe(String zipCode){
List<User> users = mBusinessLogic.getUsersByZipcode(zipCode);
if(users == null || users.size() < 1){
return null;
}
List<String> names = new ArrayList<String>();
int totalUsers = users.size();
for(int i = 0; i < totalUsers; i++){
User user = users.get(i);
String name = user.getName();
names.add(name);
//<#DEBUG_AREA>
Log.e("LogginUserInfo", "Name: " + name);
Log.e("LogginUserInfo", "Id: " + user.getId());
Log.e("LogginUserInfo", "Id: " + user.getDistance());
//</#DEBUG_AREA>
}
return names;
}
And when you change your build variant to release it would become something like this:
private List<String> getNamesOfUsersNearMe(String zipCode){
List<User> users = mBusinessLogic.getUsersByZipcode(zipCode);
if(users == null || users.size() < 1){
return null;
}
List<String> names = new ArrayList<String>();
int totalUsers = users.size();
for(int i = 0; i < totalUsers; i++){
User user = users.get(i);
String name = user.getName();
names.add(name);
/*<#DEBUG_OFF>
Log.e("LogginUserInfo", "Name: " + name);
Log.e("LogginUserInfo", "Id: " + user.getId());
Log.e("LogginUserInfo", "Id: " + user.getDistance());
</#DEBUG_OFF>*/
}
return names;
}
Which is way better in performance for long loops and makes your code cleaner by getting rid of the unnecessary code while in "release" mode, of course if you go back to "debug" it will uncomment the area and leave it the way it originally was with the "<#DEBUG_AREA>" tags...
Also trying to fit the most common scenarios, seems like there's times when you don't need a full area to get rid of but instead only one single Log, so for that case the project also has a Log wrapper class that you can use as follows:
if(users == null || users.size() < 1){
ASDebuggerMacroLog.e("LogUserInfo", "There's no users available near me...");
return null;
}
The line of code used by the class "ASDebuggerMacroLog" will be commented after changing to "release" mode in your Android Studio.
Hope it Helps!
Regards!
Standard outputs should not be used directly to log anything (squid:S106)
When logging a message there are several important requirements which must be fulfilled:
The user must be able to easily retrieve the logs
The format of all logged message must be uniform to allow the user to easily read
the log
Logged data must actually be recorded
Sensitive data must only be logged securely
If a program directly writes to the standard outputs, there is absolutely no way to comply with those requirements. That's why defining and using a dedicated logger is highly recommended.
Source: Sonarcloud
I highly recommend using Timber library: https://github.com/JakeWharton/timber
It's a very small library on top of Android Log class which takes care of all logging requirements easily. some features:
It automatically figures out which class is being called and use its name as TAG
You can plant different Tree for each build type
All logs going through a central place in Tree. so you process them or upload them somewhere if needed.
I am a beginner in android programming.
I want to use the hidden method "getState()" of "com.android.internal.telephony.call" package to manage the state of an outgoing call such as activating, ringing, answering, rejecting and disconnecting.
But there is an error in the following code on the line indicated by "**".
Any help?
My code is :
import com.android.internal.telephony.*;
public class MainActivity extends Activity {
Class myclass;
ClassLoader cloader;
Method f;
Object o;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
cloader = this.getClass().getClassLoader();
try {
myclass = cloader.loadClass("com.android.internal.telephony.Call");
// No error generated. "Call" class will be loaded.
}
catch (Exception e)
{
System.out.println(e.toString());
}
try {
f = myclass.getMethod("getState", null);
// No error generated.Method "f" will be assigned
} catch (Exception e) {
System.out.println(e.toString());
}
Constructor constructors[] = myclass.getDeclaredConstructors();
// There is one constructor only
Constructor constructor = null;
for (int i=0; i<constructors.length;i++)
{
constructor = constructors[i];
if (constructor.getGenericParameterTypes().length == 0)
break;
}
constructor.setAccessible(true);
try {
o = constructor.newInstance(null);
//*****an exception generated here.
//*****Exception is "java.lang.instantationexception"
}
catch (Exception e) {
System.out.println(e.toString());
}
try {
f = myclass.getMethod("getState", null);
// No error
} catch (Exception e) {
System.out.println(e.toString());
}
}
Don't try to call private members like this. It will not work across Android versions and even across manufacturer customized ROMs of the same version.
I want to throw an exception in Android so that the app is shut down and a the user gets the ability to report this error to the developer.
I put this into a UI class:
throw new Exception("error...");
but I get an unhandled error. When I use RuntimeException it wont crash and end my application.
You can put in try ... catch a messagebox that ask to you customer to send an email to developer and on the response you can shut down your application.
try {
......
} catch (Exception e) {
dialog.setMessage("Your Message " + e.toString() + ". Send Email?");
dialog.setButtonNegativeText("NO");
dialog.setButtonPositiveText("YES");
dialog.show(getFragmentManager(), "NoticeDialogFragment");
}
Create a user defined exception and throw the exception in the catch block..
MyOwnExceptionClass.java
public class MyOwnExceptionClass extends Exception {
private int price;
public MyOwnExceptionClass(int price){
this.price = price;
}
public String toString(){
return "Price should not be in negative, you are entered" +price;
}
}
your working class
public class Client {
public static void main(String[] args)throws Exception
{
int price = -120;
if(price < 0)
throw new MyOwnExceptionClass(price);
else
System.out.println("Your age is :"+price);
}
}
I throw a exception with some message like:
public static ILSResponseEmailLookUPBO getILSUserAccounts(Resources res,
String email) throws TripLoggerCustomException,
TripLoggerUnexpectedErrorException {
String resp = null;
String lookupURL;
try {
lookupURL = TripLoggerConstants.ServerConstants.ILS_LOOKUP_URL
+ URLEncoder.encode(email, "UTF-8");
} catch (UnsupportedEncodingException e1) {
throw new TripLoggerCustomException(
res.getString(R.string.error_try_again));
}
try {
resp = ConnectionManager.getInstance().httpRequest(lookupURL,
TripLoggerConstants.RequestMethods.GET);
} catch (IOException e) {
if (e.getMessage().equals(
res.getString(R.string.network_unreachable))
|| e.getMessage().equals(
res.getString(R.string.host_unresolved))) {
throw new TripLoggerCustomException(
res.getString(R.string.network_not_reachable));
} else {
throw new TripLoggerCustomException(
res.getString(R.string.email_notfound_ils));
}
}
here my else part execute.
And my exception class is:
public class TripLoggerCustomException extends Exception {
private String customMessage;
private static final long serialVersionUID = 1L;
public TripLoggerCustomException() {
super();
}
public TripLoggerCustomException(String message) {
super(message);
this.customMessage = (message == null ? "" : message);
}
public String getCustomMessage() {
return this.customMessage;
}
public void setCustomMessage(String customMessage) {
this.customMessage = customMessage;
}
}
And here i catch this exception:
private void manageLookUpActions(final String emailID) {
new Thread() {
public void run() {
try {
listILSAccounts = ILSLookupEmailBL.getILSUserAccounts(
getResources(), emailID);
} catch (TripLoggerCustomException e) {
dismissProgressBar();
handleException(e.getMessage());
return;
} catch (TripLoggerUnexpectedErrorException e) {
dismissProgressBar();
handleException(e.getMessage());
return;
}
}
}.start();
}
but here in catch of TripLoggerCustomException e is null.why?Can anyone help me?
After looking into multiple reports on StackOverflow, it seems like this is not an actual issue. Multiple people have been saying that it is a problem in the combination of the Eclipse debugger and the Android Emulator. That is why you don't get a NullPointerException, which you would definitely get if e was null.
So this is probably not an issue you have to worry about.