I am completely new to android, and pretty much a Java newb.
I have a simple app that I am building to get the hang of android's development environment - and things like click events, etc..
The app loads, and I am able to change the text in a textfield using a button handler. However, when I import the location class, and try to do a simple GPS call, the application crashes.
The problem is, everything looks good in Eclipse (error console) - and I'm not seeing any exceptions in the android emulator (DevTools). I have the logcat window open, but I haven't done anything in eclipse/code to send logcat anything (do I need to?)
Can anyone see something wrong with this? Is there a better way to troubleshoot?
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.*;
import android.location.*;
public class locationDisplay extends Activity {
private EditText text;
private Location GPSLocation;
double dblLat;
double dblong;
String strLat;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main); // bind the layout to the activity
text = (EditText) findViewById(R.id.EditText01);
text.setText("No button pressed");
}
// Handler for each button -- Button01 is when it crashes
public void myClickHandler(View view) {
switch (view.getId()) {
case R.id.Button01:
dblLat = GPSLocation.getLatitude();
strLat = Double.toString(dblLat);
text.setText(strLat);
break;
case R.id.Button02:
text.setText("Button 2 was clicked");
break;
case R.id.Button03:
text.setText("Button 3 was clicked");
break;
}
}
You shouldn't need to write anything to get the default messages in LogCat; uncaught exception reports should appear automatically when your program crashes. However, sometimes LogCat and your emulator get disconnected from each other and the messages simply all disappear. Simply close Eclipse and the emulator, restart them both, and the messages should reappear. An easy way to tell whether the link has been re-established is during the boot-up of the emulator. Just as the flashing "ANDROID" text in the fancy font disappears bringing you to the lockscreen, you should see about a hundred lines of text flash by on LogCat. If that doesn't happen, then LogCat isn't getting its messages.
The way to display debugging messages in Android is to use the Log.d("some name for your log statements so you can filter the LogCat messages", "The actual debug statement here");. You'll often find people using things like a static final String LOG_TAG in their application so that they can make sure their logs always have the same tag, and hence, the filter never misses a message.
As for your actual code here, Rpond is right, you never initialised your GPSLocation object.
You GPSLocation object is null. You need to access the LocationService to get a current location. And with the emulator you will need to manually send locations.
Location Services
Sometimes LogCat 'forgets' you have a device/emulator connected and running. It seems like this happens after you have a device and an emulator online at the same time and then you disconnect one of them. If you are getting nothing from LogCat, go to Window>Show View>Other>Devices and then click the device that you want to log.
Related
I've been trying to get errors to display in a text field within the app for ease of error reporting from users.
I've had some success using this code I found on stackoverflow. It's used at the top level of the app but it's not working on device:
//start code
this.loaderInfo.uncaughtErrorEvents.addEventListener(UncaughtErrorEvent.UNCAUGHT_ERROR, errorHandler);
function globalErrorHandler(event:UncaughtErrorEvent):void
{
var message:String;
//check for runtime error
if (event.error is Error)
message = (event.error as Error).getStackTrace();
//handle other errors
else if (event.error is ErrorEvent)
message = (event.error as ErrorEvent).text;
else
message = event.error.toString();
//do something with message (eg display it in textfield)
myTextfield.text = message;
}
//end code
At first this wouldn't work on the device and I thought it was because upon the error, when developing on the pc, flashplayer would display the actionscript popup with the error. Which you would need to click "dismiss all" or close and then the globalErrorHandler was called after and then the error written to the textfield. I thought this is what was keeping it from showing up on the device. However, by adding event.preventDefault() I was able to suppress the actionscript popup when developing on the desktop and the error was written to the textfield successfully. This was not the case however on the andriod device. It still just hangs on the error. It's as if the default error event cannot be suppressed on android.
Thanks for your time. Any help appreciated!
EDIT 22/09/2017: I was able to see the error on device finally. It had to do with while on desktop publishing the error would be shown. However, on device the behavior was different and something was covering the textfield, by bring it to the front on error I was able to see it. However, I still see that some errors deeper in the class hierarchy are not being caught.
In our project we have it simpler (and it is working):
stage.loaderInfo.uncaughtErrorEvents.addEventListener(UncaughtErrorEvent.UNCAUGHT_ERROR, onUncaughtError);
private function onUncaughtError(e:UncaughtErrorEvent):void
{
// Console is basically a TextField for debug/diagnosis output.
if (e.error) Console.error(e.error.getStackTrace());
e.preventDefault();
}
The other thing you should probably check is whether your TextField actually displays any text at all for there might be text embedding issues, unrelated to the error handling routine.
UPD: Loading SWFs so it doesn't mix with the parent.
var request:URLRequest = new URLRequest(path);
var context:LoaderContext = new LoaderContext;
context.applicationDomain = ApplicationDomain.currentDomain;
var loader:Loader = new Loader;
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
loader.load(request, context);
I have two issues with this, my very first android app. The first is that I noticed after I installed the app the battery started draining about twice as fast as before. I read an article on this that stated sometimes programmers make an error which causes this. This being my first app, the probability is pretty high that this is the case.
The second issue is that I can save my variables when the app is turned off, but when the phone is turned off the data is lost.
As for the code, it's mostly bits and pieces from stuff I've found online and tried to incorporate. It's a simple calculator with three variables. Ideally, I'd like to store b and c, but allow the user to overwrite them. Variable a will change with each use, so no need to store that.
Here's my Main:
package com.kwagz.calc;
import android.app.Activity;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends Activity {
String g, e;
String b; //changed(sorry)
String c; //changed
SharedPreferences sh_Pref;
Editor toEdit;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
loadSavedPreferences();
}
public void calculateClickHandler(View view) {
if (view.getId() == R.id.button1) {
EditText a = (EditText)findViewById(R.id.a);
EditText b = (EditText)findViewById(R.id.b);
EditText c = (EditText)findViewById(R.id.c);
TextView output = (TextView)findViewById(R.id.textView9);
double gp = Double.parseDouble(a.getText().toString());
int ab = Integer.parseInt(b.getText().toString());
int ac = Integer.parseInt(c.getText().toString());
double t = ((gp / ab) * ac);
output.setText(String.format("%.2f", t));
}
}
public void sharedPreferences() {
SharedPreferences saved_values =//there's no linebreak here in my code
PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
SharedPreferences.Editor editor=saved_values.edit();
editor.putString("b", b);
editor.putString("c", c);
editor.commit();
}
private void loadSavedPreferences() {
SharedPreferences saved_values =//there's no linebreak here in my code
PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
b = saved_values.getString("b", g);
}
}
From reading what you said, the only logical explanation forming in my head is: You are starting background service from your App, while background service is running it makes app run all the time which explains why variables are stored until phone is turned off (when background service gets killed).
Okay, let's take your questions one at a time. The battery problem could be a number of things, without knowing more details about your program I couldn't possibly diagnose it completely. Android does have some good power saving tips. The key item is to minimize the use of connectivity devices to no more than is required. The two biggest culprits are GPS and Internet connections. If your app isn't running, then the only way it could be running the batteries is if there's threads in the background, or maybe something like an AlarmService.
You are using SharedPreferences correctly, the value should be saved, but I think you should but the saving code in onSaveInstanceState(). If you do that, it should work fine.
EDIT
Upon closer inspection, you're fundementally saving the wrong thing. You should save the value of the EditText, not the EditText itself. In fact, I'd simply remove all references to String a,b,c, move the EditText definitions to the top to replace them, and do something like this:
editor.putString("b", b.getText().toString());
b.setText(saved_values.getString("b", g));
I've conducted several tests in an effort to recreate the issue, with no success. I'm still working on the sharedPreferences thing, but the battery drain (I suspect) was caused by another app which just happened to coincide with the installation of mine.
As I mentioned in my note to arleitiss, my Y!Mail was showing the highest amount of battery drain. A day or two after posting the note my account started acting up and then became "inactive". Once I reset it, the app no longer appears on the Battery list.
Thanks for all the input!
I have created an application that extensively requires user inputs and interaction and even though I have made sure that I test and catch every possible case that might throw an error I want to be able to create a mechanism that traces the error in case my application crashes on the field.
I want to be able to record the entire flow right from a button click till whatever the user might be selecting or the navigation between the pages in a log file such that in case my application crashes I'm able to study the trace file later and know exactly where the error occurred.
I'm very new to this sort of programming and therefore any pointers on the above will be very helpful! Thank you in advance :]
PS: I'm not even sure whether what im referring to will be correctly called a "log trace" or not so any edit is welcome. :)
EDIT : I also want to be able to save the error report generated and send it to a particular id (similar to 'send an error report to xyz).
UPDATE :
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
try {
File myFiles = new File("/sdcard/ScanApp");
if(!myFiles.exists())
{
myFiles.mkdirs();
}
File myFile = new File("sdcard/ScanApp/log.txt");
myFile.createNewFile();
myFile.delete();
myFile.createNewFile();
String cmd = "logcat -d -v time -f "+myFile.getAbsolutePath()+ " -s ActivityManager:V";
Runtime.getRuntime().exec(cmd);
Logs.this.finish();
}
catch (Exception e)
{
flag=1;
error=e.getMessage();
}
I used this in a previous application for recording any application activity and make a textfile and save it to the SD card, but the contents weren't exactly what I was looking for. Is the solution im looking for something along these lines?
Here, check for the link for reference.
In here you create a class say ExceptionHandler that implements java.lang.Thread.UncaughtExceptionHandler..
Inside this class you will do your life saving stuff like creating stacktrace and gettin ready to upload error report etc....
Now comes the important part i.e. How to catch that exception.
Though it is very simple. Copy following line of code in your each Activity just after the call of super method in your overriden onCreate method.
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler(this));
Your Activity may look something like this…
public class ForceClose extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler(this));
setContentView(R.layout.main);
}
}
Hope this helps...
You need to look up on Exception Handling. That is when your application crashes or any other app level errors occur, the code in the exception block executes. So in that place, log that error in a text-file and which solves your "log trace" issue.
Refer the link for beautiful examples.
Is it possible to capture MMI result in Android?
I need to do things like put on hold, merge calls, etc. and as the only telephony events in android are NEW_OUTGOING_CALL, RINGING, OFFHOOK and IDLE, I need to get the result when i dial any MMI code like Held Code.
Is it possible?
The best solution for me would be to find some way to discover when an outgoing call gets actually connected. Maybe has somebody find any workaround for that?
I made some progress in that question reading system logs (LogCat) and searching for determinate strings, but it seems that logs differs between models and SO versions so this is not a consistent aproach.
Thanks for your help!
Maybe you can get it using RIL(Radio Interface Layer)
try something like:
1) adb device shell
2) logcat -b radio
// Navigate to the page that you have dial *#06# in dialpad then execute jar below to get the IMEI result
import com.android.uiautomator.core.UiObject;
import com.android.uiautomator.testrunner.UiAutomatorTestCase;
import com.android.uiautomator.core.UiSelector;
import com.android.uiautomator.core.UiObjectNotFoundException;
import com.android.uiautomator.core.UiScrollable;
import android.util.Log;
public class SIM_Info_Reader_png extends UiAutomatorTestCase{
public void getPromptedIMEI() throws UiObjectNotFoundException {
UiObject list = new UiObject(new UiSelector().resourceId("android:id/text1"));
int i = 0;
System.out.println("IMEI=" + list.getText());
}
}
I have been trying to get a bitmap screenshot of a SurfaceView for days but the more I look into it, there doesn't seem to be a solution at present for Android OS 2.3.4 based OSs my device from HTC.
So on to Plan B, where I just found out another blog: "On my HTC Evo 3d, all I have to do is hold the power button for 1-2 sec and then hit the home button and it takes a screen shot. No app required." Turns out this works perfectly on my tablet.
I also know from digging around there are these intents: android.intent.action.SCREEN_OFF & android.intent.category.HOME
(So I tried a bunch of code experiments to try to mimic the 2-key combo in code to get a screenshot in this brute force manor. Unfortunately without success).
So my ? -- Does anyone have any insights into a method to invoke this 'screenshot sequence' for my HTC device from java code? (Presume I need to fool the OS into thinking I am holding down the power key AND tap the Home key, simultaneously)...
More: Here is a snip of the code I am attempting:
Button click for test... ...
Thread t = new Thread() {
public void run() {
Instrumentation inst = new Instrumentation();
inst.sendKeyDownUpSync(KeyEvent.KEYCODE_POWER);
Instrumentation inst2 = new Instrumentation();
inst2.sendKeyDownUpSync(KeyEvent.KEYCODE_HOME);
} // run
}; // thread t
Doesnt work as the inst.sendKeyDownUpSync is wrong as I need a sendKeyDown (& hold) behavior or its equivel
Many thanks for any advise. If I do get this working, I will post the solution here. Cheers GH
PS; I presume there is some custom intent under the hood doing this? Is there a system log somewhere to trey to peek at the call tree to find out what it is ?
EDIT (MORE)... 9/24/11
More. Still not working but I am heading down this path & think it is closer...
// Attempt to SIMULATE A Long press (DOWN) + HOME to tell the HTC to invoke the 'Screenshot' command (WARNING: HTC Tablet specific behavior!)
Thread tt = new Thread() {
public void run() {
final KeyEvent dapowerkey = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_POWER);
Handler onesecondhandler = new Handler();
onesecondhandler.postDelayed(new Runnable() {
public void run() {
// fpr about 1 second send power down keystrokes (DOWN ONLY)
while (true) { dispatchKeyEvent(dapowerkey); }
} // we are done running on the timer past time point
}, 750); // 3/4 second key press
// send the HOME keystroke
Instrumentation inst1 = new Instrumentation();
inst1.sendKeyDownUpSync(KeyEvent.KEYCODE_HOME);
} // outer thread run tp mpt block the GUI
}; // outer thread t
tt.start();
...
Also thought if I can send the right intent directly to the proper place on the device that I might be able to kick off a screen capture function directly (which is what I really want. Through some log examinations (when you Long-Power + Home click on HTC) a program called 'com.htc.mysketcher' (FlashActivity) is being called...
Again, if I figure this out then I will post to the group... Cheers GH