I've done it before. It's not rocket science. A beautiful activity containing a perfect form. An EditText here... A Spinner there. But this time there are CheckBox'es.
This should be easy: setup the onClick() method declared in the XML, grab the ID of the view...
...thing is, I've been using a Bundle to gather all the data in the form together and send to my IntentService to drop into the SQLite database.
/**
* Called when the user changes the state of any CheckBox
* #param view The View that was checked/unchecked */
public void onCheckBoxChng(View view) {
// Is the view now checked?
boolean checked = ((CheckBox) view).isChecked();
String mField = new String();
// Check which checkbox was clicked
switch(view.getId()){
case R.id.dlg_add_ply_chk1:
mField = "Platinum";
break;
case R.id.dlg_add_ply_chk2:
mField = "Gold";
break;
case R.id.dlg_add_ply_chk3:
mField = "Silver";
break;
case R.id.dlg_add_ply_chk4:
mField = "Bronze";
break;
case R.id.dlg_add_ply_chk5:
mField = "HQ";
break;
case R.id.dlg_add_ply_chk6:
mField = "Aurora-1";
break;
}
if (checked) {
setBundleChk(mField,1);
} else {
setBundleChk(mField,0);
}
}
/**
* Set the boolean fields in mBdlgForm based on user action on the checkboxes
*
* #param Field The field name to change
* #param State The state to set (<code>true</code> or <code>false</code> */
private void setBundleChk(String Field, int State){
if (BuildConfig.DEBUG) {
Log.i(Constants.TAG_ACTDLGADDPLYR,
"setBundleChk(Field, State) called with: "+Field+", and "+State);
Log.i(Constants.TAG_ACTDLGADDPLYR, "setBundleChk(): mBdlgForm Keys :");
for (String key: mBdlgForm.keySet()){
Log.d (Constants.TAG_FRGACTPLAYERS, "mBdlgForm."+key);
}
}
if (State == 1) {
mBdlgForm.putBoolean(Field, true);
} else {
mBdlgForm.putBoolean(Field, false);
}
}
Piece of cake, right?
Problem is, though the Bundle's scope is the entire activity, it can't been seen in the onClick() callback for the CheckBox'es NOR in any function I call from the onClick() callback...
...Please tell me... What am I missing?
Even after implementing "Activity.this.method()" I'm still getting the following Logcat messages:
03-04 20:09:32.349: E/AndroidRuntime(641): FATAL EXCEPTION: main
03-04 20:09:32.349: E/AndroidRuntime(641): java.lang.IllegalStateException: Could not execute method of the activity
03-04 20:09:32.349: E/AndroidRuntime(641): at android.view.View$1.onClick(View.java:3591)
03-04 20:09:32.349: E/AndroidRuntime(641): at android.view.View.performClick(View.java:4084)
03-04 20:09:32.349: E/AndroidRuntime(641): at android.widget.CompoundButton.performClick(CompoundButton.java:100)
03-04 20:09:32.349: E/AndroidRuntime(641): at android.view.View$PerformClick.run(View.java:16966)
03-04 20:09:32.349: E/AndroidRuntime(641): at android.os.Handler.handleCallback(Handler.java:615)
03-04 20:09:32.349: E/AndroidRuntime(641): at android.os.Handler.dispatchMessage(Handler.java:92)
03-04 20:09:32.349: E/AndroidRuntime(641): at android.os.Looper.loop(Looper.java:137)
03-04 20:09:32.349: E/AndroidRuntime(641): at android.app.ActivityThread.main(ActivityThread.java:4745)
03-04 20:09:32.349: E/AndroidRuntime(641): at java.lang.reflect.Method.invokeNative(Native Method)
03-04 20:09:32.349: E/AndroidRuntime(641): at java.lang.reflect.Method.invoke(Method.java:511)
03-04 20:09:32.349: E/AndroidRuntime(641): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
03-04 20:09:32.349: E/AndroidRuntime(641): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
03-04 20:09:32.349: E/AndroidRuntime(641): at dalvik.system.NativeStart.main(Native Method)
03-04 20:09:32.349: E/AndroidRuntime(641): Caused by: java.lang.reflect.InvocationTargetException
03-04 20:09:32.349: E/AndroidRuntime(641): at java.lang.reflect.Method.invokeNative(Native Method)
03-04 20:09:32.349: E/AndroidRuntime(641): at java.lang.reflect.Method.invoke(Method.java:511)
03-04 20:09:32.349: E/AndroidRuntime(641): at android.view.View$1.onClick(View.java:3586)
03-04 20:09:32.349: E/AndroidRuntime(641): ... 12 more
03-04 20:09:32.349: E/AndroidRuntime(641): Caused by: java.lang.NullPointerException
03-04 20:09:32.349: E/AndroidRuntime(641): at net.clmitchell.ewtraker.pPlayers.ActDlgAddPlyr.setBundleChk(ActDlgAddPlyr.java:260)
03-04 20:09:32.349: E/AndroidRuntime(641): at net.clmitchell.ewtraker.pPlayers.ActDlgAddPlyr.onCheckBoxChng(ActDlgAddPlyr.java:231)
03-04 20:09:32.349: E/AndroidRuntime(641): ... 15 more
The two line identified at the end are, respectively:
if (checked){ActDlgAddPlyr.this.setBundleChk(mField,1);}
for (String key: ActDlgAddPlyr.this.mBdlgForm.keySet()){
The following is the 2nd method:
/**
* Set the boolean fields in mBdlgForm based on user action on the checkboxes
*
* #param Field The field name to change
* #param State The state to set (<code>true</code> or <code>false</code> */
private void setBundleChk(String Field, int State){
if (BuildConfig.DEBUG) {
Log.i(Constants.TAG_ACTDLGADDPLYR, "setBundleChk(Field, State) called with: "+Field+", and "+State);
Log.i(Constants.TAG_ACTDLGADDPLYR, "setBundleChk(): mBdlgForm Keys :");
for (String key: ActDlgAddPlyr.this.mBdlgForm.keySet()){
Log.d (Constants.TAG_FRGACTPLAYERS, "mBdlgForm."+key);
}
}
if(State == 1){ActDlgAddPlyr.this.mBdlgForm.putBoolean(Field, true);}
else{ActDlgAddPlyr.this.mBdlgForm.putBoolean(Field, false);}
}
Try this out:-
Activity.this.setBundleChk(mField,1);
It seems your problem is a NullPointerException when you try to add the checked state to the Bundle. Have you properly initialized your Bundle?
The onClick xml attribute should just work. I used it a few times without any issues.
I assume that your xml has this attribute set to onCheckBoxChng:
Just be sure to declare the public void onCheckBoxChng(View view) as a proper method of your activity (not a static method, not a method of an inner class of you Activity, etc). When it is called, the this in your onCheckBoxChng method should be the Activity you expect, the one that hosts these CheckBoxes.
Based on the stack-trace, it seems that your onCheckBoxChng is actually invoked, however, the onCheckBoxChng method throws an exception, which was caused by a null pointer exception in setBundleChk.
What code is on line 260, inside your setBundleChk method? If it is String key: ActDlgAddPlyr.this.mBdlgForm.keySet() then it looks like the mBdlgForm is null. The mBdlgForm Bundle is there, it can be 'seen'. It is just null. Make sure you assign a proper value to mBdlgForm before any onclicks are handled.
Problem solved.
Valuable lessons learned:
It was a mistake to try and get the CheckBox data at the moment the user touched a CheckBox; I needed to trust the Android OS and gather the data AFTER the user pressed the "Save" Button using tried and true techniques.
Using "android:onClick" is useful in certain situations, but one must be sure when such an approach is appropriate.
You can use an Intent ANYWHERE in an Activity, not just to communicate with another Activity. In this case the Intent class saved my bacon: declaring a method as a listener cuts it off from nearly everything in an Activity BUT THE INTENT; I was able to grab my Activity's existing Intent, add the user input to it, then access and validate that data from where I would run the actual INSERT:
// Grab the current Activity's Intent
Intent iNewPlyr = getIntent();
// Put the bundle containing user input into the Intent
iNewPlyr.putExtras(mB);
// process and INSERT the data from somewhere else
validate();
I am grateful to everyone who chimed in...may all your stock options triple in value!
Related
I'm fairly new to Android and am having an issue with fetching data from my database. I have an activity class which calls the database helper to get a list of questions according to a particular category. The database should then put all of the questions into an ArrayList and return them. The error seems to be occurring when I try and get the first question in the list of questions using:
Question question = questions.get(0);
Here is the relevant method in the activity class:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_atomic_structure_questions);
DatabaseHelper database = new DatabaseHelper(getApplicationContext());
List<Question> questions = database.getQuestions(1);
Question question = questions.get(0);
TextView questionText = (TextView) findViewById(R.id.QuestionText);
questionText.setText(question.getText());
}
Database Helper:
// Get All The Question From Database For A Specific Category And Put Them Into A List Of Question
public List<Question> getQuestions(int category) {
List<Question> questions = new ArrayList<Question>();
String selectQuery = "SELECT * FROM " + TABLE_QUESTION +
" WHERE " + KEY_CATEGORY_ID + " = '" + category + "'";
Log.e(LOG, selectQuery);
database = this.getReadableDatabase();
Cursor cursor = database.rawQuery(selectQuery, null);
if (cursor.moveToFirst()) {
// Loops Through The Database To Get All Question Matching Category
do {
Question question = new Question();
question.setId(cursor.getInt(cursor.getColumnIndex(KEY_QUESTION_ID)));
question.setNumber(cursor.getInt(cursor.getColumnIndex(KEY_QUESTION_NUMBER)));
question.setText(cursor.getString(cursor.getColumnIndex(KEY_QUESTION_TEXT)));
question.setMarks(cursor.getInt(cursor.getColumnIndex(KEY_QUESTION_MARKS)));
question.setAnswer(cursor.getInt(cursor.getColumnIndex(KEY_QUESTION_ANSWER)));
question.setMC1(cursor.getString(cursor.getColumnIndex(KEY_QUESTION_MC1)));
question.setMC2(cursor.getString(cursor.getColumnIndex(KEY_QUESTION_MC2)));
question.setMC3(cursor.getString(cursor.getColumnIndex(KEY_QUESTION_MC3)));
question.setMC4(cursor.getString(cursor.getColumnIndex(KEY_QUESTION_MC4)));
// Add The Question To The List Of Question
questions.add(question);
} while (cursor.moveToNext());
}
return questions;
}
Finally, here is the logcat:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.revision.aschemistry/com.revision.aschemistry.AtomicStructureQuestions}: java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1956)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981)
at android.app.ActivityThread.access$600(ActivityThread.java:123)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4424)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:787)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:554)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0
at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:251)
at java.util.ArrayList.get(ArrayList.java:304)
at com.revision.aschemistry.AtomicStructureQuestions.onCreate(AtomicStructureQuestions.java:26)
at android.app.Activity.performCreate(Activity.java:4465)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1920)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981)
at android.app.ActivityThread.access$600(ActivityThread.java:123)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4424)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:787)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:554)
at dalvik.system.NativeStart.main(Native Method)
Any help is much appreciated, thanks in advance.
It seems your ArrayList Question is Empty. So just check size before getting data from it.
List<Question> questions = database.getQuestions(1);
if(!questions.isEmpty())
{
Question question = questions.get(0);
}else
{
Log.e("LOG","questions is Empty")
}
Also check Cursor size in your getQuestions() method from DatabaseHelper class.
Obviously you can use:
if(!questions.isEmpty())
To avoid the the ArrayIndexOutOfBounds Exception. But I guess that dosen't Solve our problem dose it?
I hope our solution here is to read the data properly and then retrieve the data using the get() method of Arraylist.
There needs to be a check before reading the data. Please check if the data are feed properly first and then go for getting them. I would like to suggest some posts you can follow to get idea about Databases.
http://www.vogella.com/tutorials/AndroidSQLite/article.html
http://infobloggall.com/2014/05/06/sqlite-database-example
Also the developer site.
In my MainActivity I call this code to change to a new fragment, I pass a bundle with parcelable object, itemModel to the fragment:
Bundle bundle = new Bundle();
bundle.putParcelable(ItemModel.ParcelableKey, itemModel);
fragment = new AppFragment();
fragment.setArguments(bundle);
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.frame_container, fragment).addToBackStack(null).commit();
In the fragment, I receive the parcel back like this:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mItemModel = getArguments().getParcelable(ItemModel.ParcelableKey);
//....other code.....
}
When I test it locally, the code works fine on my test device, mItemModel is able to be retrieved back properly, however, I have integrated crash report system into the app (Crashlytics), and the report states a log like this on a release:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.temp.test/com.temp.test.MainActivity}: java.lang.NullPointerException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2114)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2139)
at android.app.ActivityThread.access$700(ActivityThread.java:143)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1241)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4960)
at java.lang.reflect.Method.invokeNative(Method.java)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1038)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:805)
at dalvik.system.NativeStart.main(NativeStart.java)
Caused by: java.lang.NullPointerException
at android.os.Parcel.readStringArray(Parcel.java:931)
at com.temp.test.data.ItemModel.<init>(ItemModel.java:478)
at com.temp.test.data.ItemModel.<init>(ItemModel.java:23)
at com.temp.test.data.ItemModel$1.createFromParcel(ItemModel.java:445)
at com.temp.test.data.ItemModel$1.createFromParcel(ItemModel.java:443)
at android.os.Parcel.readParcelable(Parcel.java:2103)
at android.os.Parcel.readValue(Parcel.java:1965)
at android.os.Parcel.readMapInternal(Parcel.java:2226)
at android.os.Bundle.unparcel(Bundle.java:223)
at android.os.Bundle.getParcelable(Bundle.java:1165)
at com.temp.test.fragments.AppFragment.onCreateView(AppFragment.java:98)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:829)
at android.app.FragmentManagerImpl.moveTo## Heading ##State(FragmentManager.java:1035)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1017)
at android.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1804)
at android.app.Activity.performCreate(Activity.java:5206)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1094)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2078)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2139)
at android.app.ActivityThread.access$700(ActivityThread.java:143)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1241)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4960)
at java.lang.reflect.Method.invokeNative(Method.java)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1038)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:805)
at dalvik.system.NativeStart.main(NativeStart.java)
at com.temp.test.fragments.AppFragment.onCreateView(AppFragment.java:98) <-- This error line leads to this line in the source code:
mItemModel = getArguments().getParcelable(ItemModel.ParcelableKey);
It is very strange because it works well in my local device. So I dived a little deeper into Bundle's source code, I noticed that in unparcel(), it has a checking like this at the beginning:
synchronized void unparcel() {
if (mParcelledData == null) {
if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this)) + ": no parcelled data");
return;
}
//....other code.....
}
The strange thing is that mParcelledData should be null in my case, because I created Bundle like this Bundle bundle = new Bundle(); as shown in my code snippet above, so in my case it should be using mMap instead of mParcelledData.
Question: what are the possible cases that getArguments() in fragment's onCreateView() will return a Bundle with non-null mParcelledData?
OR
In what cases that mItemModel = getArguments().getParcelable(ItemModel.ParcelableKey); will perform differently in my local test device vs production release for end user?
I am very new to android. I have a counter on some SomeActivity, but when I get to the page corresponding to SomeActivity, my app crashes :
final TextView counter = (TextView) findViewById(R.id.laws_counter);
ImageView handDown = (ImageView) findViewById(R.id.handViewDown);
counter.setText("" + 0);
I want that on click of the handown, the counter is idented by -1. Here's
handDown.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(NewsActivity.this,
"The favorite list would appear on clicking this icon",
Toast.LENGTH_LONG).show();
setDown();
}
private void setDown() {
String count = counter.getText().toString();
int now_count = Integer.parseInt(count) +1;
counter.setText(String.valueOf(now_count));
}
});
Is this code correct ?
Update : here's the logcat
10-22 00:18:05.579: ERROR/AndroidRuntime(378): FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.donnfelker.android.bootstrap/com.donnfelker.android.bootstrap.ui.NewsActivity}: java.lang.NullPointerException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1647)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663)
at android.app.ActivityThread.access$1500(ActivityThread.java:117)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:3683)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
at com.donnfelker.android.bootstrap.ui.NewsActivity.onCreate(NewsActivity.java:41)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611)
... 11 more
There are many ways that you can implement that functionality but think this would be an easy solution.
Make a helper method:
public class PreferencesData {
public static void saveInt(Context context, String key, int value) {
SharedPreferences sharedPrefs = PreferenceManager
.getDefaultSharedPreferences(context);
sharedPrefs.edit().putInt(key, value).commit();
}
public static int getInt(Context context, String key, int defaultValue) {
SharedPreferences sharedPrefs = PreferenceManager
.getDefaultSharedPreferences(context);
return sharedPrefs.getInt(key, defaultValue);
}
}
Then simply call the putInt method to save the counter in any Activity and getInt to get it again in any other Activity. As long as you use the same key both places.
excuse the trouble I was trying to make a listview for parsing a page for my app, I'll explain: I have a actionbar formed by Fragment.
When instazia the fragment, opening the app the first time "getActivity" does not return null, is the next time, when I start the AsyncTask
In the fragment in which I will stop parsing this error:
java.lang.NullPointerException
at android.widget.ArrayAdapter.init(ArrayAdapter.java:310)
at android.widget.ArrayAdapter.<init>(ArrayAdapter.java:104)
at com.megadown.megacodownloader.ParsingArrayAdapter.<init>(ParsingArrayAdapter.java:30)
at com.megadown.megacodownloader.Tab_Search$ParsingPaginaWeb.onPostExecute(Tab_Search.java:264)
at com.megadown.megacodownloader.Tab_Search$ParsingPaginaWeb.onPostExecute(Tab_Search.java:125)
at android.os.AsyncTask.finish(AsyncTask.java:631)
at android.os.AsyncTask.access$600(AsyncTask.java:177)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:644)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4898)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1006)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:773)
at dalvik.system.NativeStart.main(Native Method)
Code Java that refers:
protected void onPostExecute(String result)
{
// dopo che ho eseguito il parsing mostro i dati nella listview
adapter = new ParsingArrayAdapter(myActivity, titoli, descrizioni,immagini);
lista.setAdapter(adapter);
}
If you want I can post the code of the ArrayAdapter.
Thank you in advance
First, make sure myActivity has the correct value:
protected void onPostExecute(String result) {
Activity myActivity = getActivity();
adapter = new ParsingArrayAdapter(myActivity, titoli, descrizioni,immagini);
lista.setAdapter(adapter);
}
Next, point is, you can't be sure that your activity and fragment is still active in onPostExecute().
For example, the user could have pressed 'back' button or rotated the screen, which would re-create the activites and fragments.
So, the good code is:
protected void onPostExecute(String result) {
Activity myActivity = getActivity();
if (myActivity==null) return; // Fragment not active anymore, bail out
adapter = new ParsingArrayAdapter(myActivity, titoli, descrizioni,immagini);
lista.setAdapter(adapter);
}
Fragment's getActivity() will only return expectable value while the associated activity has done onCreate method.
I have been trying to program a twitter client for Android (using twitter4j). So far the idea is to have a simple GUI, and if there is not a file with the OAuth token in the SD Card, connect to the Twitter API using AsyncTask, get the URL for the authorization and open the default browser. However, the browser never runs. Depending on the different modifications I have made trying to fix this, either the Activity starts normally but the browser never starts or the Activity crashes. I have come to a point of a a little of frustation and confussion. Can someone point out what's wrong with my code?
public class StatusActivity extends Activity {
private static final String TAG = "StatusActivity";
EditText editText;
Button updateButton;
File oauthfile = null;
public Context context = getApplicationContext();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_status);
Log.d(TAG, "started");
// Find views
editText = (EditText) findViewById(R.id.editText); //
updateButton = (Button) findViewById(R.id.buttonUpdate);
oauthfile = new File("sdcard/auth_file.txt");
//Check if the file with the keys exist
if (oauthfile.exists()==false){
Log.d(TAG, "file not created");
Context context = getApplicationContext();
Toast toast = Toast.makeText(context, "file not created.", Toast.LENGTH_SHORT);
toast.show();
new Authorization(context).execute();
}
}
public void openBrowser (View v){
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.google.com"));
startActivity(browserIntent);
Log.d(TAG, "onclick");
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.status, menu);
return true;
}
}
class Authorization extends AsyncTask <String, Integer, String>{
String url = null;
private Context context;
Authorization(Context context) {
this.context = context.getApplicationContext();
}
public void onPreExecute() {
super.onPreExecute();
Toast.makeText(context, "Invoke onPreExecute()", Toast.LENGTH_SHORT).show();
}
#Override
public String doInBackground(String... params) {
ConfigurationBuilder configBuilder = new ConfigurationBuilder();
configBuilder.setDebugEnabled(true)
//I have eliminated the keys from the question :)
.setOAuthConsumerKey("XXXXXXXXXXXXXX")
.setOAuthConsumerSecret("XXXXXXXXXXXXXXX");
Twitter OAuthTwitter = new TwitterFactory(configBuilder.build()).getInstance();
RequestToken requestToken = null;
AccessToken accessToken = null;
do{
try {
requestToken = OAuthTwitter.getOAuthRequestToken();
url = requestToken.getAuthorizationURL();
}
catch (TwitterException ex) {
ex.printStackTrace();
}
}
while (accessToken==null);
return url;
}
protected void onPostExecute(String result) {
super.onPostExecute(result);
Toast.makeText(context, "Opening browser.", Toast.LENGTH_SHORT).show();
Intent browserIntent = new Intent(Intent.ACTION_ALL_APPS, Uri.parse(url));
context.startActivity(browserIntent);
}
}
I know that at least checks if the file for the tokens exists because the toast "file not created" appears, and that the activity is able to run the browser if I press the button. The app has permissions to write in the SD card and use the Internet. Thanks in advance.
Logcat Trace:
03-28 19:02:32.816: E/AndroidRuntime(278): FATAL EXCEPTION: main
03-28 19:02:32.816: E/AndroidRuntime(278): java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.versec.pardinus/com.versec.pardinus.StatusActivity}: java.lang.NullPointerException
03-28 19:02:32.816: E/AndroidRuntime(278): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2585)
03-28 19:02:32.816: E/AndroidRuntime(278): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
03-28 19:02:32.816: E/AndroidRuntime(278): at android.app.ActivityThread.access$2300(ActivityThread.java:125)
03-28 19:02:32.816: E/AndroidRuntime(278): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
03-28 19:02:32.816: E/AndroidRuntime(278): at android.os.Handler.dispatchMessage(Handler.java:99)
03-28 19:02:32.816: E/AndroidRuntime(278): at android.os.Looper.loop(Looper.java:123)
03-28 19:02:32.816: E/AndroidRuntime(278): at android.app.ActivityThread.main(ActivityThread.java:4627)
03-28 19:02:32.816: E/AndroidRuntime(278): at java.lang.reflect.Method.invokeNative(Native Method)
03-28 19:02:32.816: E/AndroidRuntime(278): at java.lang.reflect.Method.invoke(Method.java:521)
03-28 19:02:32.816: E/AndroidRuntime(278): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
03-28 19:02:32.816: E/AndroidRuntime(278): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
03-28 19:02:32.816: E/AndroidRuntime(278): at dalvik.system.NativeStart.main(Native Method)
03-28 19:02:32.816: E/AndroidRuntime(278): Caused by: java.lang.NullPointerException
03-28 19:02:32.816: E/AndroidRuntime(278): at android.content.ContextWrapper.getApplicationContext(ContextWrapper.java:100)
03-28 19:02:32.816: E/AndroidRuntime(278): at com.versec.pardinus.StatusActivity.<init>(StatusActivity.java:30)
03-28 19:02:32.816: E/AndroidRuntime(278): at java.lang.Class.newInstanceImpl(Native Method)
03-28 19:02:32.816: E/AndroidRuntime(278): at java.lang.Class.newInstance(Class.java:1429)
03-28 19:02:32.816: E/AndroidRuntime(278): at android.app.Instrumentation.newActivity(Instrumentation.java:1021)
03-28 19:02:32.816: E/AndroidRuntime(278): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2577)
03-28 19:02:32.816: E/AndroidRuntime(278): ... 11 more
This is what is causing your crash.
public Context context = getApplicationContext();
You're not even using it when you need it, so you can just get rid of this line.
Btw, something else I noticed while looking at your code is this:
oauthfile = new File("sdcard/auth_file.txt");
Don't take the "sdcard/" path for granted. Use this instead:
File dir = Environment.getExternalStorageDirectory();
File oauthfile = new File(dir, "auth_file.txt");