2015-11-14 1 views
5

Sto provando a scrivere il plugin per ottenere l'applist con il nome e l'icona del pacchetto nel react-native. Ricevo tutti i dati richiesti sotto forma di JSONArray e le immagini vengono memorizzate nella sdcard.Qual è la causa di questo problema "Impossibile convertire l'argomento di tipo class org.json.JSONArray" in Android reattivo?

Sto utilizzando il callback per restituire il risultato (array JSON) su javascript (riuscito o non riuscito). Sto ottenendo l'errore di cui sopra.

Si prega di trovare il codice java che sta recuperando i dettagli come di seguito.

pacchetto com.sampleapp;

import com.facebook.react.ReactPackage; 
import com.facebook.react.bridge.Callback; 
import com.facebook.react.bridge.JavaScriptModule; 
import com.facebook.react.bridge.NativeModule; 
import com.facebook.react.bridge.ReactApplicationContext; 
import com.facebook.react.bridge.ReactContext; 
import com.facebook.react.bridge.ReactContextBaseJavaModule; 
import com.facebook.react.bridge.ReactMethod; 
import com.facebook.react.uimanager.ViewManager; 
import com.facebook.react.views.drawer.ReactDrawerLayoutManager; 
import com.facebook.react.views.image.ReactImageManager; 
import com.facebook.react.views.progressbar.ReactProgressBarViewManager; 
import com.facebook.react.views.scroll.ReactHorizontalScrollViewManager; 
import com.facebook.react.views.scroll.ReactScrollViewManager; 
import com.facebook.react.views.switchview.ReactSwitchManager; 
import com.facebook.react.views.text.ReactRawTextManager; 
import com.facebook.react.views.text.ReactTextViewManager; 
import com.facebook.react.views.text.ReactVirtualTextViewManager; 
import com.facebook.react.views.textinput.ReactTextInputManager; 
import com.facebook.react.views.toolbar.ReactToolbarManager; 
import com.facebook.react.views.view.ReactViewManager; 
import com.facebook.react.views.viewpager.ReactViewPagerManager; 

public class ToastModule extends ReactContextBaseJavaModule { 
    private static final String DURATION_SHORT_KEY = "SHORT"; 
    private static final String DURATION_LONG_KEY = "LONG"; 
    public static JSONArray applist; 

    public ToastModule(ReactApplicationContext reactContext) { 
     super(reactContext); 
    } 

    @Override 
    public String getName() { 
     return "ToastAnd"; 
    } 

    @ReactMethod 
    public void show(Callback errorCallback, Callback successCallback) { 
     try { 
      //get a list of installed apps. 
      PackageManager pm = getReactApplicationContext().getPackageManager(); 
      List<ApplicationInfo> packages = pm.getInstalledApplications(0); 

      JSONArray app_list = new JSONArray(); 
      int cnt = 0; 
      String path = getSDPath(); 
      makeRootDirectory(path + "/com.framework.xxx/"); 
      makeRootDirectory(path + "/com.framework.xxx/Cache/"); 
      for (ApplicationInfo packageInfo : packages) { 
       try { 

        if (getReactApplicationContext().getPackageManager().getLaunchIntentForPackage(packageInfo.packageName) != null) { 
         JSONObject info = new JSONObject(); 
         info.put("name", packageInfo.loadLabel(pm)); 
         info.put("packagename", packageInfo.packageName); 
         String img_name = "/com.ionicframework.xxx/Cache/" + packageInfo.packageName + ".png"; 
         info.put("img", path + img_name); 
         //cheak exist or not 
         File cheakfile = new File(path + img_name); 
         if (!cheakfile.exists()) { 

          Drawable icon = pm.getApplicationIcon(packageInfo); 
          if (icon != null) { 
           drawableTofile(icon, path + img_name); 
          } 
         } 
         app_list.put(cnt++, info); 
        } 
       } catch (Exception ex) { 
        System.err.println("Exception: " + ex.getMessage()); 
       } 
      } 
      applist = app_list; 
      successCallback.invoke(applist); 

     } catch (Exception e) { 
      errorCallback.invoke(e.getMessage()); 
     } 
    } 

    public static void drawableTofile(Drawable drawable,String path) 
    { 
     File file = new File(path); 
     Bitmap bitmap=((BitmapDrawable)drawable).getBitmap(); 
     ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
     bitmap.compress(Bitmap.CompressFormat.PNG, 100 /*ignored for PNG*/, bos); 
     byte[] bitmapdata = bos.toByteArray(); 


     //write the bytes in file 
     FileOutputStream fos; 
     try { 
      fos = new FileOutputStream(file); 
      fos.write(bitmapdata); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

    } 

    public String getSDPath() 
    { 
     File SDdir = null; 
     boolean sdCardExist= Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED); 
     if(sdCardExist){ 
      SDdir=Environment.getExternalStorageDirectory(); 
     } 
     if(SDdir!=null){ 

      return SDdir.toString(); 
     } 
     else{ 
      return null; 
     } 
    } 

    public static void makeRootDirectory(String filePath) { 
     File file = null; 
     try { 
      file = new File(filePath); 
      if (!file.exists()) { 
       file.mkdirs(); //make Directory 
      } 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 
} 

Negli android.index.js sto chiamando il metodo nativo come illustrato di seguito:

/** 
* Sample React Native App 
* https://github.com/facebook/react-native 
*/ 
'use strict'; 

var React = require('react-native'); 

var { 
    AppRegistry, 
    StyleSheet, 
    Text, 
    View, 
} = React; 

var toastMessage = require('./sampleToast'); 
toastMessage.show(
    (msg) => { console.log(msg); }, 
    (result) => { alert(JSON.stringify(result)); } 

); 

var SampleApp = React.createClass({ 
    render: function() { 
    return (
     <View style={styles.container}> 
     <Text style={styles.welcome}> 
      Welcome to React Native! 
     </Text> 
     <Text style={styles.instructions}> 
      To get started, edit index.android.js 
     </Text> 
     <Text style={styles.instructions}> 
      Shake or press menu button for dev menu 
     </Text> 
     </View> 
    ); 
    } 
}); 

var styles = StyleSheet.create({ 
    container: { 
    flex: 1, 
    justifyContent: 'center', 
    alignItems: 'center', 
    backgroundColor: '#F5FCFF', 
    }, 
    welcome: { 
    fontSize: 20, 
    textAlign: 'center', 
    margin: 10, 
    }, 
    instructions: { 
    textAlign: 'center', 
    color: '#333333', 
    marginBottom: 5, 
    }, 
}); 

AppRegistry.registerComponent('SampleApp',() => SampleApp); 

Ma l'nel codice Java, mentre restituire l'APPLIST (successCallback.invoke (APPLIST);) sto ricevendo l'errore sopra menzionato.

potresti aiutarmi dove sto sbagliando. Grazie

errore dettagliata:

Exception in native call from JS 
11-14 09:01:24.780 20592-20624/com.sampleapp E/unknown:React: java.lang.RuntimeException: Cannot convert argument of type class org.json.JSONArray 
11-14 09:01:24.780 20592-20624/com.sampleapp E/unknown:React:  at com.facebook.react.bridge.Arguments.fromJavaArgs(Arguments.java:55) 
11-14 09:01:24.780 20592-20624/com.sampleapp E/unknown:React:  at com.facebook.react.bridge.CallbackImpl.invoke(CallbackImpl.java:27) 
11-14 09:01:24.780 20592-20624/com.sampleapp E/unknown:React:  at com.sampleapp.ToastModule.show(ToastModule.java:100) 
11-14 09:01:24.780 20592-20624/com.sampleapp E/unknown:React:  at java.lang.reflect.Method.invokeNative(Native Method) 
11-14 09:01:24.780 20592-20624/com.sampleapp E/unknown:React:  at java.lang.reflect.Method.invoke(Method.java:515) 
11-14 09:01:24.780 20592-20624/com.sampleapp E/unknown:React:  at com.facebook.react.bridge.BaseJavaModule$JavaMethod.invoke(BaseJavaModule.java:106) 
11-14 09:01:24.780 20592-20624/com.sampleapp E/unknown:React:  at com.facebook.react.bridge.NativeModuleRegistry$ModuleDefinition.call(NativeModuleRegistry.java:143) 
11-14 09:01:24.780 20592-20624/com.sampleapp E/unknown:React:  at com.facebook.react.bridge.NativeModuleRegistry.call(NativeModuleRegistry.java:64) 
11-14 09:01:24.780 20592-20624/com.sampleapp E/unknown:React:  at com.facebook.react.bridge.CatalystInstance$NativeModulesReactCallback.call(CatalystInstance.java:366) 
11-14 09:01:24.780 20592-20624/com.sampleapp E/unknown:React:  at com.facebook.react.bridge.queue.NativeRunnable.run(Native Method) 
11-14 09:01:24.780 20592-20624/com.sampleapp E/unknown:React:  at android.os.Handler.handleCallback(Handler.java:733) 
11-14 09:01:24.780 20592-20624/com.sampleapp E/unknown:React:  at android.os.Handler.dispatchMessage(Handler.java:95) 
11-14 09:01:24.780 20592-20624/com.sampleapp E/unknown:React:  at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(MessageQueueThreadHandler.java:31) 
11-14 09:01:24.780 20592-20624/com.sampleapp E/unknown:React:  at android.os.Looper.loop(Looper.java:136) 
11-14 09:01:24.780 20592-20624/com.sampleapp E/unknown:React:  at com.facebook.react.bridge.queue.MessageQueueThread$1.run(MessageQueueThread.java:137) 
11-14 09:01:24.780 20592-20624/com.sampleapp E/unknown:React:  at java.lang.Thread.run(Thread.java:841) 

risposta

7

Quando si lavora ponti nativi, callback deve essere richiamato con WritableNative componenti dalla confezione com.facebook.react.bridge.

Invece di un JSONObject, utilizzare WritableNativeMap.
Invece di JSONArray, utilizzare WritableNativeArray.

Ad esempio, con un WritableNativeMap:

@ReactMethod 
public void reactMethod(Callback onSuccess) { 
    WritableMap resultData = new WritableNativeMap(); 
    resultData.putString("key1", "data"); 
    resultData.putString("key2", "data2"); 

    onSuccessCallback(resultData); 
} 

Nel tuo caso, si dovrebbe avere qualcosa di simile:

public static WritableArray applist; 

// ... 

@ReactMethod 
public void show(Callback errorCallback, Callback successCallback) { 
    try { 
     //get a list of installed apps. 
     PackageManager pm = getReactApplicationContext().getPackageManager(); 
     List<ApplicationInfo> packages = pm.getInstalledApplications(0); 

     WritableArray app_list = new WritableNativeArray(); 

     // ... 

     for (ApplicationInfo packageInfo : packages) { 
      try { 

       if (getReactApplicationContext().getPackageManager().getLaunchIntentForPackage(packageInfo.packageName) != null) { 
        WritableMap info = new WritableNativeMap(); 
        info.putString("name", packageInfo.loadLabel(pm).toString()); 
        info.putString("packagename", packageInfo.packageName); 

        // ... 

        app_list.pushMap(info); 
       } 
      } catch (Exception ex) { 
       System.err.println("Exception: " + ex.getMessage()); 
      } 
     } 
     applist = app_list; 
     successCallback.invoke(applist); 

    } catch (Exception e) { 
     errorCallback.invoke(e.getMessage()); 
    } 
} 
+0

Grazie per la risposta Almouro. Non ti ho preso. Puoi spiegare un po 'per favore. Vuoi dire che devo archiviare in forma di valore chiave? – coders

+0

Quando provo a scrivere come hai detto, il suo display Eccezione: org.json.JSONArray non può essere lanciato su com.facebook.react.bridge.WritableArray error – coders

+0

Il mio male, non ho letto il tuo codice accuratamente. Sto modificando la mia risposta. – Almouro