Android - Fragment onCreate crashes when app starts

1.9k Views Asked by At

Hi Im working on a fragment that has a button that will allow the user to choose a picture for upload. However when trying to test the fragment it crashes. Where it states that its crashing, if I remove the code then the button shows and I can go to my gallery to choose a picture but once I click on the picture the app crashes again.

Logcat -

  10-01 01:18:39.618    7982-7982/com.myapp.app.myapp E/AndroidRuntime﹕ FATAL EXCEPTION: main
    java.lang.NullPointerException
            at com.myapp.app.myapp.Social.model.UserProfiles.ProfilePic.onCreate(ProfilePic.java:49)
            at android.support.v4.app.Fragment.performCreate(Fragment.java:1481)
            at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:908)
            at android.support.v4.app.FragmentManagerImpl.performPendingDeferredStart(FragmentManager.java:838)
            at android.support.v4.app.Fragment.setUserVisibleHint(Fragment.java:843)
            at android.support.v4.app.FragmentPagerAdapter.setPrimaryItem(FragmentPagerAdapter.java:130)
            at android.support.v4.view.ViewPager.populate(ViewPager.java:1071)
            at android.support.v4.view.ViewPager.populate(ViewPager.java:919)
            at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1441)
            at android.view.View.measure(View.java:15291)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4819)
            at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
            at android.view.View.measure(View.java:15291)
            at android.widget.LinearLayout.measureVertical(LinearLayout.java:861)
            at android.widget.LinearLayout.onMeasure(LinearLayout.java:602)
            at android.view.View.measure(View.java:15291)
            at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4819)
            at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
            at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2421)
            at android.view.View.measure(View.java:15291)
            at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:1867)
            at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1111)
            at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1292)
            at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1009)
            at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4242)
            at android.view.Choreographer$CallbackRecord.run(Choreographer.java:725)
            at android.view.Choreographer.doCallbacks(Choreographer.java:555)
            at android.view.Choreographer.doFrame(Choreographer.java:525)
            at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:711)
            at android.os.Handler.handleCallback(Handler.java:615)
            at android.os.Handler.dispatchMessage(Handler.java:92)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:4941)
            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:794)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:561)
            at dalvik.system.NativeStart.main(Native Method)

Here's the fragment -

import android.app.Activity;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

import com.kii.cloud.storage.KiiObject;
import com.kii.cloud.storage.resumabletransfer.KiiRTransfer;
import com.kii.cloud.storage.resumabletransfer.KiiRTransferCallback;
import com.kii.cloud.storage.resumabletransfer.KiiUploader;
import com.myapp.app.myapp.R;

import java.io.File;
import java.io.FileOutputStream;

public class ProfilePic extends Fragment {
    private static final String TAG = "ProfilePic";
    String objectUri = null;
    private static final int PICK_IMAGE = 1;
    private Activity activity;
private View view;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_attach_file, container,
                false);
        return view;
    }
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        objectUri = getArguments().getString("object_uri");
        Button attachButton = (Button)
                getView().findViewById(R.id.attach_file_button);
        attachButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                onAttachFileButtonClicked(v);
            }
        });
        setPageImage(3);
        ImageView imageView = (ImageView) getView().findViewById(R.id.details);
        imageView.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {

            }
        });
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        this.activity = activity;
    }

    @Override
    public void onDetach() {
        super.onDetach();
        this.activity = null;
    }

    public void onAttachFileButtonClicked(View v) {
        Intent intent = new Intent();
        intent.setType("image/*");
        intent.setAction(Intent.ACTION_GET_CONTENT);
        startActivityForResult(
                Intent.createChooser(intent, "Select Picture"), PICK_IMAGE);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == PICK_IMAGE && resultCode == Activity.RESULT_OK) {
            Uri selectedFileUri = data.getData();
            String filePath = getFilePathByUri(selectedFileUri);
            Log.v(TAG, "Picture Path : " + filePath);
            if (filePath == null) {
                showAlert("File not exists, Please select an image that exists locally.");
                return;
            }
            uploadFile(filePath);
        } else {
            showToast("picking file failed!");
        }
    }

    private void showToast(String message) {
        Toast.makeText(this.activity, message, Toast.LENGTH_SHORT).show();
    }

    private String getFilePathByUri(Uri selectedFileUri) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            // Workaround of retrieving file image through ContentResolver
            // for Android4.2 or later
            String filePath = null;
            FileOutputStream fos = null;
            try {
                Bitmap bmp = MediaStore.Images.Media.getBitmap(
                        this.activity.getContentResolver(), selectedFileUri);

                String cacheDir = Environment.getExternalStorageDirectory()
                        .getAbsolutePath() + File.separator + "app";
                File createDir = new File(cacheDir);
                if (!createDir.exists()) {
                    createDir.mkdir();
                }
                filePath = cacheDir + File.separator + "upload.jpg";
                File file = new File(filePath);

                fos = new FileOutputStream(file);
                bmp.compress(CompressFormat.JPEG, 95, fos);
                fos.flush();
                fos.getFD().sync();
            } catch (Exception e) {
                filePath = null;
            } finally {
                if (fos != null) {
                    try {
                        fos.close();
                    } catch (Exception e) {
                        // Nothing to do
                    }
                }
            }
            return filePath;
        } else {
            String[] filePathColumn = { MediaStore.MediaColumns.DATA };
            Cursor cursor = this.activity.getContentResolver().query(
                    selectedFileUri, filePathColumn, null, null, null);

            if (cursor == null)
                return null;
            try {
                if (!cursor.moveToFirst())
                    return null;
                int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
                if (columnIndex < 0) {
                    return null;
                }
                String picturePath = cursor.getString(columnIndex);
                return picturePath;
            } finally {
                cursor.close();
            }
        }
    }

    private void uploadFile(String path) {
        KiiObject object = KiiObject.createByUri(Uri.parse(objectUri));
        File f = new File(path);
        Log.v(TAG, "file can read : " + f.canRead());
        KiiUploader uploader = object.uploader(this.activity, f);
        uploader.transferAsync(new KiiRTransferCallback() {

            @Override
            public void onStart(KiiRTransfer operator) {
                setFragmentProgress(View.VISIBLE);
            }

            @Override
            public void onTransferCompleted(KiiRTransfer operator, Exception e) {
                setFragmentProgress(View.INVISIBLE);
                if (e == null) {

                } else {

                }
            }
        });
    }

    public void moveFromDialogFragment(Class<?> clazz) {
        if (clazz != null) {
            Intent i = new Intent(this.activity, clazz);
            startActivity(i);
        }
    }

    void showAlert(String message) {
        DialogFragment newFragment = AlertDialogFragment.newInstance(
                R.string.operation_failed, message, null);
        newFragment.show(getFragmentManager(), "dialog");
    }

    void setFragmentProgress(int v) {
        ProgressFragment fragment = (ProgressFragment) getFragmentManager()
                .findFragmentById(R.id.progressFragment);
        if (fragment != null && fragment.isInLayout()) {
            fragment.setProgressBarVisiblity(v);
        }
    }

    void setPageImage(int page) {
        ProgressFragment fragment = (ProgressFragment) getFragmentManager()
                .findFragmentById(R.id.progressFragment);
        if (fragment != null && fragment.isInLayout()) {
            fragment.setPageImage(page);
        }
    }
}

Any other code needed for assistance please let me know.

UPDATE I tried the suggestions and Im stil receiving the same error. It seems to fail right at -

 objectUri = args.getString("object_uri");

UPDATE 2 I tried the code suggested and still received the same error at the same line. I updated my code and logcat to reflect the changes made.

Thanks

3

There are 3 best solutions below

6
On

A view which is returned by onCreateView() is set to a root view of the fragment. Use getView() method of Fragment class instead of view in onActivityCreated().

UPDATE

In Fragment lifecycle, when Fragment is added, the callback methods will be called in regular sequence. onAttach() -> onCreate() -> onCreateView() -> onActivityCreated().

onCreateView() instantiates a fragment’s view and the view is set to a root view. Your code is correct. However, onCreate() is called before onCreateView(). The root view of the fragment hasn’t be set yet in onCreate(). You can’t use getView() method in onCreate(). It will return null.

I recommend that you use onActivityCreated() instead of onCreate() to access the fragment's view.

Change

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

to

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
9
On

Change

 View view = inflater.inflate(R.layout.fragment_attach_file, container,false);

to

view = inflater.inflate(R.layout.fragment_attach_file, container,false);

you do not need declare it again because it is already declare at private View view; of your class. When you declare it again in your method it takes the assignment to itself, so your member variable left null.

Shadowing

Update

@Override
public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      objectUri = getArguments().getString("object_uri");
}

UPDATE 2

you have not set any argument for your fragment and it is null.

At this line Button attachButton=(Button)getView().findViewById(R.id.attach_file_button); also getView returns null because onCreate is called before onCreateView

1
On

I find in

Button attachButton = (Button) view.findViewById(R.id.attach_file_button);

view isn't initialized. I think findViewById() should be put in onCreateView().