Android:片段未附加到活动错误

时间:2017-02-13 19:50:20

标签: java android android-fragments

所以我正在开发一款应用程序,我让这部分工作了好几天,而且没有任何地方它无缘无故地停止工作......

当我在MainActivity中尝试使用另一个无头片段时,我也遇到了同样的错误,但最终用MainActivity中的内部方法替换了片段,一切都恢复正常。

但是,我不能重写我只需避免使用片段的每一段代码。片段代码如下。

public class IMEIFragment extends Fragment implements ActivityCompat.OnRequestPermissionsResultCallback{


    public static final String TAG_IMEI = "IMEILoader";
    protected Activity mActivity;

    private String RecordedIMEI;
    //public static final String CHECK_INTERNET = "network_connection";

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return null; //Do we need this at all?
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        Activity activity = context instanceof Activity ? (Activity) context : null;
        mActivity = activity;
    }

    //Is this needed?
    @SuppressWarnings("deprecation")

    @Override
    public void onAttach(Activity activity) {
        activity = getActivity();
        if (isAdded() && activity != null) {
            super.onAttach(activity);
        }

        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            mActivity = activity;
        }
    }


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

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

    public String loadIMEI(Context context) {
        if (Build.VERSION.SDK_INT >= 23) {
            if (ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE)
                    != PackageManager.PERMISSION_GRANTED) {
                // READ_PHONE_STATE permission has not been granted.
                requestPermissions(context);
            } else {
                // READ_PHONE_STATE permission is already been granted.
                RecordedIMEI = permissionGrantedActions(context);
            }
            if (RecordedIMEI != null) {
                Log.i("loadIMEIService", "IMEI number returned!");
            }
        } else {
            // READ_PHONE_STATE permission is already been granted.
            RecordedIMEI = permissionGrantedActions(context);
        }
        if (RecordedIMEI != null) {
            Log.i("loadIMEIService", "IMEI number returned!");
        }
        return RecordedIMEI;
    }
    private void requestPermissions(Context context) {
        if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
            Log.i("loadIMEIService", "READ_PHONE_STATE permission not granted, asking for it...");

            // TODO create proper notification content


            PermissionHelper.requestPermissions(((PriceActivity) getActivity()),
                    new String[]{Manifest.permission.READ_PHONE_STATE},
                    Constants.PERM_REQUEST_PHONE_STATE,
                    getString(R.string.notify_perm_title),
                    getString(R.string.notify_perm_body),
                    R.drawable.ic_security);
        }
    }

    // Callback received when a permissions request has been completed.
    @Override
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        boolean isGranted = false;
        for (int i = 0; i < grantResults.length; i++)
            if (permissions[i].equals(Manifest.permission.READ_PHONE_STATE) && (grantResults[i] == PackageManager.PERMISSION_GRANTED))
                isGranted = true;
        if (isGranted) {
            Context context = getActivity().getApplicationContext();
            permissionGrantedActions(context);
        }
        else
            Log.w("loadIMEIService", "READ_PHONE_STATE permission not granted. loadIMEI will not be available.");
    }


    public String permissionGrantedActions(Context context) {
        //Have an  object of TelephonyManager
        TelephonyManager tm =(TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
        //Get IMEI Number of Phone
        String IMEINumber = tm.getDeviceId();

        if(IMEINumber != null) {
            Log.i("loadIMEIService", "IMEI number recorded!");
        }
        return IMEINumber;
    }
}

错误如下:

E/AndroidRuntime: FATAL EXCEPTION: main
                  Process: com.android.project1, PID: 5498
                  java.lang.RuntimeException: Unable to start activity ComponentInfo{com.android.project1/com.android.project1.main.MainActivity}: java.lang.IllegalStateException: Fragment IMEIFragment{3e80da7 IMEILoader} not attached to Activity
                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
                      at android.app.ActivityThread.-wrap11(ActivityThread.java)
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
                      at android.os.Handler.dispatchMessage(Handler.java:102)
                      at android.os.Looper.loop(Looper.java:148)
                      at android.app.ActivityThread.main(ActivityThread.java:5417)
                      at java.lang.reflect.Method.invoke(Native Method)
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
                   Caused by: java.lang.IllegalStateException: Fragment IMEIFragment{3e80da7 IMEILoader} not attached to Activity
                      at android.app.Fragment.getResources(Fragment.java:805)
                      at android.app.Fragment.getString(Fragment.java:827)
                      at com.android.project1.fragments.IMEIFragment.requestPermissions(IMEIFragment.java:107)
                      at com.android.project1.fragments.IMEIFragment.loadIMEI(IMEIFragment.java:80)
                      at com.android.project1.main.MainActivity.onCreate(MainActivity.java:108)
                      at android.app.Activity.performCreate(Activity.java:6237)
                      at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 
                      at android.app.ActivityThread.-wrap11(ActivityThread.java) 
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344) 
                      at android.os.Handler.dispatchMessage(Handler.java:102) 
                      at android.os.Looper.loop(Looper.java:148) 
                      at android.app.ActivityThread.main(ActivityThread.java:5417) 
                      at java.lang.reflect.Method.invoke(Native Method) 
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 

这是我的MainActivity的相关部分:

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

        mDeviceCode = (TextView) findViewById(R.id.device_code);

        // Initializing headless fragment
        mFragment =
                (IMEIFragment) getFragmentManager()
                        .findFragmentByTag("IMEILoader");

        if (mFragment == null) {
            mFragment = new IMEIFragment();
            getFragmentManager().beginTransaction()
                    .add(mFragment, "IMEILoader").commit();
        }
        if (mFragment != null) {
            mNumber = mFragment.loadIMEI(MainActivity.this);
            mDeviceCode.setText(Html.fromHtml("<b>IMEI</b>: " + mNumber));
        }

我确实有相同的代码工作了一个多星期。谁知道可能是什么问题?

编辑1:错误指向片段

中的requestPermissions

1 个答案:

答案 0 :(得分:0)

碎片应尽可能自包含。您正从活动

直接调用您的IMEIFragment
from functions import doSomething

var = doSomething()

你不能这样做。通过活动中的事务添加片段是异步操作。例如,当 Caused by: java.lang.IllegalStateException: Fragment IMEIFragment{3e80da7 IMEILoader} not attached to Activity at android.app.Fragment.getResources(Fragment.java:805) at android.app.Fragment.getString(Fragment.java:827) at com.android.project1.fragments.IMEIFragment.requestPermissions(IMEIFragment.java:107) at com.android.project1.fragments.IMEIFragment.loadIMEI(IMEIFragment.java:80) at com.android.project1.main.MainActivity.onCreate(MainActivity.java:108) 方法完成时,片段未初始化。而且,你无法知道它什么时候被初始化。这就是为什么它应该是自包含的。片段决定何时调用loadIMEI(),而不是活动。

如果确实需要由活动启动,您可以将片段中的回调添加到活动中,例如,

commit()

或其他什么。

是的,void onFragmentReady(Fragment f); 应该返回一些东西。如果您的片段根本没有任何用户界面,那么您就不需要它作为片段。