4

I need to add the share feature to my Android app (The app is for writing notes and store them in a SQLite database) (The share button only shares the body of the note). I did it, but when I press "Share" button, it shows FC (Force Close) and the app stops.

The code of the share feature (It's in the MainActivity class):

...
@Override
    public boolean onContextItemSelected(final MenuItem item) {
        switch (item.getItemId()) {
            case R.id.share:
                String shareBody = NotesModel.actualNote.body;
                Intent shareIntent = new Intent("android.intent.action.SEND");
                shareIntent.setType("text/plain");
                shareIntent.putExtra("android.intent.extra.TEXT", shareBody);
                startActivity(shareIntent);
                return true;
                ...

The whole MainActivity class:

package com.twitter.i_droidi.mynotesdonation;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.Toast;
import java.util.List;
import com.oguzdev.circularfloatingactionmenu.library.FloatingActionButton;

public class MainActivity extends ActionBarActivity implements AdapterView.OnItemClickListener, View.OnClickListener {

    ListView lv;
    NotesDataSource nDS;
    List<NotesModel> notesList;
    String[] notes;
    int i;
    ArrayAdapter<String> adapter;
    FloatingActionButton actionButton;
    public static final String floatingButtonTag = "";
    CheckBox checkBox;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        View checkBoxView = View.inflate(this, R.layout.checkbox, null);
        checkBox = (CheckBox) checkBoxView.findViewById(R.id.checkboxDialog);
        checkBox.setOnClickListener(this);
        loadSavedPreferences();

        checkBox.setText(R.string.do_not_show_this_again);
        final Context context = this;
        AlertDialog.Builder mainDialog = new AlertDialog.Builder(context);
        mainDialog.setTitle(R.string.thanks);
        mainDialog.setMessage(R.string.main_dialog_body);
        mainDialog.setIcon(R.drawable.my_notes);
        mainDialog.setView(checkBoxView);
        mainDialog.setPositiveButton(R.string.welcome, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                // Do Not Do Anything.
            }
        });
        AlertDialog alertDialog = mainDialog.create();
        if (checkBox.isChecked() == false) {
            alertDialog.show();
        }

        ImageView icon = new ImageView(this);
        icon.setImageDrawable(getResources().getDrawable(R.drawable.ic_action_new));

        actionButton = new FloatingActionButton.Builder(this)
                .setContentView(icon)
                .setBackgroundDrawable(R.drawable.the_selector)
                .build();
        actionButton.setOnClickListener(this);
        actionButton.setTag(floatingButtonTag);

        nDS = new NotesDataSource(this);
        lv = (ListView) findViewById(R.id.lv);

        nDS.open();
        notesList = nDS.getAllNotes();
        nDS.close();

        notes = new String[notesList.size()];

        for (i = 0; i < notesList.size(); i++) {
            notes[i] = notesList.get(i).getTitle();
        }

        adapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1,
                android.R.id.text1, notes);
        lv.setAdapter(adapter);

        registerForContextMenu(lv);
        lv.setOnItemClickListener(this);
    }

    public void loadSavedPreferences() {
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
        boolean checkBoxStatus = prefs.getBoolean("Status", false);

        if (checkBoxStatus) {
            checkBox.setChecked(true);
        } else {
            checkBox.setChecked(false);
        }
    }

    public void savePreferences(String key, boolean status) {
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);

        SharedPreferences.Editor editor = prefs.edit();
        editor.putBoolean(key, status);
        editor.commit();
    }

    @Override
    public void onClick(View v) {
        if (v.getTag() != null && v.getTag().equals(floatingButtonTag)) {
            Intent nNote = new Intent(this, CreateNote.class);
            startActivity(nNote);
        }

        savePreferences("Status", checkBox.isChecked());
    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        Intent nView = new Intent(this, ViewEditNote.class);
        nView.putExtra("id", notesList.get(position).getId());
        nView.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        startActivity(nView);
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.menu_item_selected, menu);
        super.onCreateContextMenu(menu, v, menuInfo);
    }

    @Override
    public boolean onContextItemSelected(final MenuItem item) {
        switch (item.getItemId()) {
            case R.id.share:
                String shareBody = NotesModel.body;
                Intent shareIntent = new Intent("android.intent.action.SEND");
                shareIntent.setType("text/plain");
                shareIntent.putExtra("android.intent.extra.TEXT", shareBody);
                startActivity(shareIntent);
                return true;

            case R.id.delete:
                AlertDialog.Builder deleteDialog = new AlertDialog.Builder(this);
                deleteDialog.setTitle(getString(R.string.delete_title));
                deleteDialog.setMessage(R.string.delete_body);
                deleteDialog.setIcon(R.drawable.my_notes);
                deleteDialog.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface deleteDialog, int witch) {
                        AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
                        nDS.open();
                        nDS.deleteNote(notesList.get(info.position).getId());
                        notesList = nDS.getAllNotes();
                        nDS.close();

                        notes = new String[notesList.size()];

                        for (i = 0; i < notesList.size(); i++) {
                            notes[i] = notesList.get(i).getTitle();
                        }

                        adapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1,
                                android.R.id.text1, notes);
                        lv.setAdapter(adapter);

                        registerForContextMenu(lv);
                        lv.setOnItemClickListener(MainActivity.this);

                        Toast nDelete = Toast.makeText(MainActivity.this, R.string.deleted, Toast.LENGTH_LONG);
                        nDelete.show();
                        return;
                    }
                });
                deleteDialog.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface deleteDialog, int which) {
                        // Do Not Do Anything.
                    }
                });
                deleteDialog.show();
                return true;
        }
        return super.onContextItemSelected(item);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.mainMenuAbout:
                AlertDialog.Builder aboutDialog = new AlertDialog.Builder(this);
                aboutDialog.setTitle(getString(R.string.about_title));
                aboutDialog.setMessage(R.string.about_body);
                aboutDialog.setIcon(R.drawable.my_notes);
                aboutDialog.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface aboutDialog, int witch) {
                        // Do Not Do Anything.
                    }
                });

                aboutDialog.show();
                return true;

            case R.id.mainMenuBackupHelp:
                AlertDialog.Builder backupHelpDialog = new AlertDialog.Builder(this);
                backupHelpDialog.setTitle(getString(R.string.backup_help_title));
                backupHelpDialog.setMessage(R.string.backup_help_body);
                backupHelpDialog.setIcon(R.drawable.my_notes);
                backupHelpDialog.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface backupHelpDialog, int witch) {
                        // Do Not Do Anything.
                    }
                });

                backupHelpDialog.show();
                return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

The NotesModel class:

package com.twitter.i_droidi.mynotesdonation;

public class NotesModel {

    int id;
    String title;
    String body;
    static NotesModel actualNote;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getBody() {
        return body;
    }

    public void setBody(String body) {
        this.body = body;
    }
}

The NotesDataSource class:

package com.twitter.i_droidi.mynotesdonation;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;

public class NotesDataSource {

    DB myDB;
    SQLiteDatabase sql;
    public static NotesModel note;

    String[] getAllColumns = new String[]{DB.ID, DB.TITLE, DB.BODY};

    public NotesDataSource(Context context) {
        myDB = new DB(context);
    }

    public void open() {
        try {
            sql = myDB.getWritableDatabase();
        } catch (Exception ex) {
            Log.d("Error in your database!", ex.getMessage());
        }
    }

    public void close() {
        sql.close();
    }

    public void createNote(String title, String body) {
        ContentValues note = new ContentValues();
        note.put(myDB.TITLE, title);
        note.put(myDB.BODY, body);
        sql.insert(myDB.TABLE_NAME, null, note);
    }

    public NotesModel getNote(int id) {
        note = new NotesModel();

        Cursor cursor = sql.rawQuery("SELECT * FROM " + DB.TABLE_NAME + " WHERE " + DB.ID + " = ?", new String[]{id + ""});

        if (cursor.getCount() > 0) {
            cursor.moveToFirst();
            note.setId(cursor.getInt(0));
            note.setTitle(cursor.getString(1));
            note.setBody(cursor.getString(2));
            cursor.close();
        }
        return note;
    }

    public void updateNote(int id, String title, String body) {
        ContentValues note = new ContentValues();
        note.put(myDB.TITLE, title);
        note.put(myDB.BODY, body);
        sql.update(myDB.TABLE_NAME, note, myDB.ID + " = " + id, null);
    }

    public void deleteNote(Object id) {
        sql.delete(myDB.TABLE_NAME, myDB.ID + " = " + id, null);
    }

    public List<NotesModel> getAllNotes() {
        List<NotesModel> notesList = new ArrayList<NotesModel>();

        Cursor cursor = sql.query(myDB.TABLE_NAME, getAllColumns, null, null, null, null, null);
        cursor.moveToFirst();

        while (!cursor.isAfterLast()) {
            NotesModel notes = new NotesModel();
            notes.setId(cursor.getInt(0));
            notes.setTitle(cursor.getString(1));
            notes.setBody(cursor.getString(2));

            notesList.add(notes);
            cursor.moveToNext();
        }

        cursor.close();
        return notesList;
    }
}

The logcat:

09-06 01:53:10.263  24553-24553/com.twitter.i_droidi.mynotesdonation E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.twitter.i_droidi.mynotesdonation, PID: 24553
    java.lang.NullPointerException: Attempt to read from field 'java.lang.String com.twitter.i_droidi.mynotesdonation.NotesModel.body' on a null object reference
            at com.twitter.i_droidi.mynotesdonation.MainActivity.onContextItemSelected(MainActivity.java:144)
            at android.app.Activity.onMenuItemSelected(Activity.java:2905)
            at android.support.v4.app.FragmentActivity.onMenuItemSelected(FragmentActivity.java:325)
            at android.support.v7.app.AppCompatActivity.onMenuItemSelected(AppCompatActivity.java:147)
            at android.support.v7.internal.view.WindowCallbackWrapper.onMenuItemSelected(WindowCallbackWrapper.java:100)
            at com.android.internal.policy.impl.PhoneWindow$DialogMenuCallback.onMenuItemSelected(PhoneWindow.java:4701)
            at com.android.internal.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:761)
            at com.android.internal.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:152)
            at com.android.internal.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:904)
            at com.android.internal.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:894)
            at com.android.internal.view.menu.MenuDialogHelper.onClick(MenuDialogHelper.java:167)
            at com.android.internal.app.AlertController$AlertParams$3.onItemClick(AlertController.java:1082)
            at android.widget.AdapterView.performItemClick(AdapterView.java:305)
            at android.widget.AbsListView.performItemClick(AbsListView.java:1146)
            at android.widget.AbsListView$PerformClick.run(AbsListView.java:3053)
            at android.widget.AbsListView$3.run(AbsListView.java:3860)
            at android.os.Handler.handleCallback(Handler.java:739)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5254)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
ChrisF
  • 134,786
  • 31
  • 255
  • 325
  • please can you post the logcat report – Shadow Droid Sep 06 '15 at 07:55
  • dear could you please let us know about resion of fatal. – John smith Sep 06 '15 at 07:56
  • @ShadowDroid Sorry.. I updated the post. –  Sep 06 '15 at 08:00
  • have you checked NotesModel.actualNote is null or not? before accessing the body data – Shadow Droid Sep 06 '15 at 08:00
  • @ShadowDroid I tried many times to solve this problem, but I can't. If you need more classes I will post them. –  Sep 06 '15 at 08:02
  • error is saying NotesModel.actualNote.body means there is no actualNote present or still it has not been initialized so it won't contain any body.If you are trying to follow singleton pattern then it is not right way...Also post the code where you are initializing or creating NotesModel.actualNote.body – Shadow Droid Sep 06 '15 at 08:06
  • I updated the post, check it out. –  Sep 06 '15 at 08:22

2 Answers2

1

It seems like you haven't initialised the actualNote field in the NotesModel class. Try saying

static NotesModel actualNote = new NotesModel();
Apoorva
  • 1,365
  • 1
  • 10
  • 11
0

Why you are making inner static object in this case, just use :

public class NotesModel {

    int id;
    String title;
    public static String body;

    ...
}

and fetch like :

NotesModel.body

EDIT :

Use Getter method if you do not want static identifier:

NotesModel mModel = new NotesModel();
mModel.setBody(" String with your body ");
String shareBody = mModel.getBody();    // Getter method
Kushal
  • 8,100
  • 9
  • 63
  • 82
  • This answer cause another problem here: http://stackoverflow.com/questions/32415665/declare-a-variable-as-static-cause-a-bug-in-an-android-app-for-notes –  Sep 06 '15 at 08:13
  • I checked your problem, pls check my updated solution.... – Kushal Sep 06 '15 at 08:21
  • It solves all problems, but when I share the text inside the body of the note, nothing shows or it shares an empty text. :\ –  Sep 06 '15 at 08:28
  • This is because your `body` String is null or empty.... you first call `setBody()` then call `getBody()` – Kushal Sep 06 '15 at 08:33
  • I tried with this line: `nModel.setBody(String.valueOf(NotesDataSource.note));`, but it shares "null" word! :\. Check the post out, I put the `NotesDataSource` class. –  Sep 06 '15 at 08:54
  • Have you checked `NotesDataSource.note` has not null String? – Kushal Sep 07 '15 at 04:31
  • 1
    I solved the problem by setting the button and whole code of share feature in another class (at this time only). I will try to add them to the MainActivity later. Thanks a lot for helping me. –  Sep 07 '15 at 16:47