2017-02-13 41 views
1

所以我工作的一個應用程序,我有這部分的日工作,進出沒有它只是無緣無故攔工作...安卓片段未連接到活動錯誤

我也當我嘗試在我的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我的片段內

+0

爲什麼多重覆蓋onAttach()? – CSmith

+0

@CSmith如果我沒有記錯,它是針對不同的構建版本,因爲某些方法已被棄用。我會嘗試將其中一個出來,看看它是否影響任何東西。 – Zack

+0

你當然不能從onAttach()調用getActivity()並期望它能夠工作。擺脫onAttach()覆蓋和onDetach(),它們不是必需的。如果您需要訪問上下文,請使用getActivity()。遵循@Blattman的指導 – CSmith

回答

0

片段應自包含儘可能多的。您正在從活動直接撥打您的IMEIFragment,

  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) 

您不能那樣做。通過活動中的事務添加片段是異步操作。例如,當commit()方法完成時,片段不被初始化。而且,你無法知道什麼時候被初始化。這就是爲什麼它應該是自成體系的。片段決定何時調用loadIMEI(),而不是活動。

如果你真的需要它由活動發起,您可以從片段添加一個回調的活動一樣,

void onFragmentReady(Fragment f); 

什麼的。

是的,onCreateView()應該返回一些東西。如果你的片段根本沒有任何UI,你不需要它是一個片段。

+0

我想我最想說的是你想說的話。所以,在我的MainActivity中,我應該改變這個>> if(mFragment!= null)mNumber = mFragment.loadIMEI(MainActivity.this); mDeviceCode.setText(Html.fromHtml(「IMEI:」+ mNumber));如果(mFragment!= null && mFragment.isAdded()){ } mNumber = mFragment.loadIMEI mDeviceCode.setText(Html。fromHtml(「IMEI:」+ mNumber)); } << – Zack

+0

或者我應該在onResume()內而不是從Activity中調用loadIMEI? – Zack

+0

你的活動不應該調用你的片段類的任何方法。你的片段應該把'loadIMEI()'作爲其生命週期的一部分。考慮我上面的評論重新:你真的需要一個片段? –