我正在创建一个本机安卓应用程序来访问并打印出日期/日期的部分列表中的Android手机/平板电脑的通话记录(例如,昨天; 26/07/17; 25/07/17等) ;但是当我从模块调用方法时,我仍然停留在react类中的调用日志字符串的实际打印中。显然反应方法只能“回归”无效。
我试图使用promises但却陷入了异步和等待。我不能使用npm 5(具有异步和等待的节点),因为我使用“react native init”为物理设备测试创建了一个项目;并且不支持/稳定npm(在终端上显示)。我使用“sudo npm install -g npm @ latest-4”,所以我可以使用init。
我尝试使用“npm install async --save”和“npm install asyncawait”手动安装async并等待。当我跑到后来它没有任何区别。
我真的只想在我的物理Android设备的屏幕上输出呼叫详细信息作为部分列表。
我试过google;但也许我的关键词不够好;所以我得到了一些帮助。如果你能告诉我是否需要.xml文件,如果是这样的话也会很好;看起来如何。我已经发布了我的java本机模块方法的代码和我从帮助器.js类导入模块的类。我为评论的代码道歉;我尝试了很多方法来打印。
我得到的最新错误;当我真的可以举杯时,'tag'是“未定义的不是一个对象(评估'n.data.length')”。在解决“期望组件类得到对象”和“未定义不是函数”之后。
下面的反应js类:
import React, { Component } from 'react';
import { NativeModules, AppRegistry, SectionList, StyleSheet, Text, View, WebView } from 'react-native';
import { StackNavigator, } from 'react-navigation';
import CallLogAndroid from './RctActivity';
export default class SectionListBasics extends Component {
static navigationOptions = { title: 'Your Call Logs', };
// CallLog = () =>{
// const Cllog= CallLogAndroid.getCallDetails();
// console.log(Cllog+"");
// return Cllog+"";
// };
// async function getCallLog() {
// try {
// var CallDetails = await CallLogAndroid.getCallDetails(100, 100);
// console.log(CallDetails);
// return CallDetails;
// }
// catch (e) {
// console.error(e);
// }
// }
componentWillMount() {
const log = CallLogAndroid.getCallDetails().then(function(value) {
console.log(value); // "Success"
}, function(value) {
// not called
});
}
render() {
// const divStyle = {
// WebkitTransition: 'all', // note the capital 'W' here
// msTransition: 'all' // 'ms' is the only lowercase vendor prefix
// };
// var thenProm = resolvedProm.then(function(value){
// console.log("this gets called after the end of the main stack. the value received and returned is: " + value);
// return value;
// });
console.log(this.log+"");
//getCallLog();
return (
<View style={styles.container}>
<SectionList
sections={[
{title: 'Today', data: [ 'pete'{/*this.log*/}] },
{/* <WebView source={{html: CallLogAndroid.getCallDetails()}} /> */},
{title: 'Yesterday', data: ['Jackson']},
{title: 'Date: 1', data: ['water']},
{title: 'Date: 2', data: ['dance']},
{title: 'Date: 3', data: ['rain']},
{title: 'Date: 4', data: ['Mum']},
{title: 'Date: 5', data: ['Dad']},
]}
renderItem={({item}) => <Text style={styles.item}>{item}</Text>}
renderSectionHeader={({section}) => <Text style={styles.sectionHeader}>{section.title}</Text>}
/>
{/* <Text>
console.log(CallLogAndroid.getCallDetails().toString());
</Text> */}
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: 22
},
sectionHeader: {
paddingTop: 2,
paddingLeft: 10,
paddingRight: 10,
paddingBottom: 2,
fontSize: 20,
fontWeight: 'bold',
backgroundColor: 'rgba(247,247,247,1.0)',
},
item: {
padding: 10,
fontSize: 18,
height: 44,
},
})
// skip this line if using Create React Native App
//AppRegistry.registerComponent('AwesomeProject', () => SectionListBasics);
这是java类:
package com.workingapp;
import android.widget.Toast;
//to create react bridge
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.common.MapBuilder;
import com.facebook.react.uimanager.IllegalViewOperationException;
import com.facebook.react.bridge.Promise;
//android tools imports
import android.content.Intent;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.app.Activity;
import android.Manifest;
import android.content.ContentValues;
import android.content.pm.PackageManager;
import android.provider.CallLog;
import android.provider.CallLog.Calls;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.database.Cursor; //import cursor to parse call logs
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.app.LoaderManager;
import android.content.CursorLoader;
import android.content.Loader;
import android.os.Bundle;
import android.text.Html; //import html to make *online query to content provider
import android.util.Log;
import android.view.View;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;
import android.widget.ImageView;
import android.view.Gravity; //import gravity to centre layout
import android.view.ViewGroup;
import android.view.LayoutInflater;
import java.util.Map;
import java.net.*; //import uri - a Uniform Resource Identifier (URI) is a string of characters used to identify a resource. Such identification enables interaction with representations of the resource over a network
import java.util.Date;
import android.widget.TextView;
import java.util.HashMap;
//Customised versions of loader imported
import android.support.v4.app.FragmentActivity;
//import android.support.v4.app.LoaderManager;
//import android.support.v4.content.Loader;
//Specific imports for inflator in toast
import java.io.UnsupportedEncodingException;
import java.util.zip.DataFormatException;
import java.util.zip.Deflater;
import java.util.zip.Inflater;
public class CallLogModule extends ReactContextBaseJavaModule implements LoaderManager.LoaderCallbacks<Cursor>{
public static final String REACT_CLASS = "CallLogAndroid";
private static final String E_LAYOUT_ERROR = "E_LAYOUT_ERROR";
ReactApplicationContext reactContext;
private static HashMap<String, String> rowDataCall;
private static final String TAG = "CallLog";
private static final int URL_LOADER = 1;
private static TextView callLogsTextView;
// @Override
// public void onCreate(Bundle savedInstanceState) {
// super.onCreate(savedInstanceState);
// Log.d(TAG, "onCreate()");
// setContentView(R.layout.main);
// initialize();
// }
/**Constructor */
public CallLogModule(ReactApplicationContext reactContext) {
super(reactContext);
this.reactContext= reactContext;
//(Activity)reactContext.setContentView(R.layout.module_layout);
}
/**Loads all calls */
@Override
@ReactMethod
public Loader onCreateLoader(int loaderID, Bundle args) {
Log.d(TAG, "onCreateLoader() >> loaderID : " + loaderID);
switch (loaderID) {
case URL_LOADER:
// Returns a new CursorLoader
return new CursorLoader(
reactContext, // Parent activity context
CallLog.Calls.CONTENT_URI, // Table to query
null, // Projection to return
null, // No selection clause
null, // No selection arguments
null // Default sort order
);
default:
return null;
}
}
/**On completing load, return/output formatted string*/
@Override
@ReactMethod
public void onLoadFinished(Loader loader, Cursor managedCursor) {
Log.d(TAG, "onLoadFinished()");
StringBuilder sb = new StringBuilder();
int number = managedCursor.getColumnIndex(CallLog.Calls.NUMBER);
int type = managedCursor.getColumnIndex(CallLog.Calls.TYPE);
int date = managedCursor.getColumnIndex(CallLog.Calls.DATE);
int duration = managedCursor.getColumnIndex(CallLog.Calls.DURATION);
sb.append("<h4>Call Log Details <h4>");
sb.append("\n");
sb.append("\n");
sb.append("<table>");
while (managedCursor.moveToNext()) {
String phNumber = managedCursor.getString(number);
String callType = managedCursor.getString(type);
String callDate = managedCursor.getString(date);
//Date callDayTime = new Date(Long.valueOf(callDate));
Date callDayTime= null;
if( (!callDate.trim().equals("") ) && (callDate != null)) {
callDayTime = new Date(Long.valueOf(callDate)); //if value of long is null
}
String callDuration = managedCursor.getString(duration);
String dir = null;
int callTypeCode = Integer.parseInt(callType);
switch (callTypeCode) {
case CallLog.Calls.OUTGOING_TYPE:
dir = "Outgoing";
break;
case CallLog.Calls.INCOMING_TYPE:
dir = "Incoming";
break;
case CallLog.Calls.MISSED_TYPE:
dir = "Missed";
break;
}
sb.append("<tr>")
.append("<td>Phone Number: </td>")
.append("<td><strong>")
.append(phNumber)
.append("</strong></td>");
sb.append("</tr>");
sb.append("<br/>");
sb.append("<tr>")
.append("<td>Call Type:</td>")
.append("<td><strong>")
.append(dir)
.append("</strong></td>");
sb.append("</tr>");
sb.append("<br/>");
sb.append("<tr>")
.append("<td>Date & Time:</td>")
.append("<td><strong>")
.append(callDayTime)
.append("</strong></td>");
sb.append("</tr>");
sb.append("<br/>");
sb.append("<tr>")
.append("<td>Call Duration (Seconds):</td>")
.append("<td><strong>")
.append(callDuration)
.append("</strong></td>");
sb.append("</tr>");
sb.append("<br/>");
sb.append("<br/>");
}
sb.append("</table>");
managedCursor.close();
callLogsTextView.setText(Html.fromHtml(sb.toString()),TextView.BufferType.SPANNABLE);
}
@Override
@ReactMethod
public void onLoaderReset(Loader<Cursor> loader) {
Log.d(TAG, "onLoaderReset()");
// do nothing
}
/**Method to obtain name of the class */
@Override
public String getName() {
return REACT_CLASS;
}
/**Method to get entire call log */
// @ReactMethod
// public void getCallLog(String phone,int duration) {
// //Checking if permission was denied
// if (ActivityCompat.checkSelfPermission(getCurrentActivity(), Manifest.permission.READ_CALL_LOG) != PackageManager.PERMISSION_GRANTED){
// ActivityCompat.requestPermissions(getCurrentActivity(), new String[]{Manifest.permission.READ_CALL_LOG}, 101);
// }
// //uses a cursor to get all calls
// else{
// Uri allCalls = Uri.parse("content://call_log/calls");
// Cursor c = managedQuery(allCalls, null, null, null, null);
// //separates calls according to number; name; duration and Call type
// String num= c.getString(c.getColumnIndex(CallLog.Calls.NUMBER));// for number
// String name= c.getString(c.getColumnIndex(CallLog.Calls.CACHED_NAME));// for name
// String duration = c.getString(c.getColumnIndex(CallLog.Calls.DURATION));// for duration
// int type = Integer.parseInt(c.getString(c.getColumnIndex(CallLog.Calls.TYPE)));// for call type, Incoming or out-going.
// //Print calls in a certain format
// }
// }
/**Method to get full list of call logs */
@ReactMethod
private void getCallDetails(Promise promise) {
try{
StringBuffer sb = new StringBuffer();
Uri contacts = CallLog.Calls.CONTENT_URI;
Cursor managedCursor = (reactContext.getCurrentActivity()).getContentResolver().query(contacts, null, null, null, null);
int number = managedCursor.getColumnIndex(CallLog.Calls.NUMBER);
int type = managedCursor.getColumnIndex(CallLog.Calls.TYPE);
int date = managedCursor.getColumnIndex(CallLog.Calls.DATE);
int duration = managedCursor.getColumnIndex(CallLog.Calls.DURATION);
//sb.append("Call Details :");
sb.append("<h1>Call Log Details </h1>"); //tried to print out with react syntax contrary to code commented below
sb.append("\n");
sb.append("\n");
sb.append("<table>");
while (managedCursor.moveToNext()) {
rowDataCall = new HashMap<String, String>();
String phNumber = managedCursor.getString(number);
String callType = managedCursor.getString(type);
String callDate = managedCursor.getString(date);
String callDayTime = new Date(Long.valueOf(callDate)).toString();
// long timestamp = convertDateToTimestamp(callDayTime);
String callDuration = managedCursor.getString(duration);
String dir = null;
int dircode = Integer.parseInt(callType);
switch (dircode) {
case CallLog.Calls.OUTGOING_TYPE:
dir = "OUTGOING";
break;
case CallLog.Calls.INCOMING_TYPE:
dir = "INCOMING";
break;
case CallLog.Calls.MISSED_TYPE:
dir = "MISSED";
break;
}
// sb.append("\nPhone Number:--- " + phNumber + " \nCall Type:--- " + dir + " \nCall Date:--- " + callDayTime + " \nCall duration in sec :--- " + callDuration);
// sb.append("\n----------------------------------");
sb.append("<tr>")
.append("<td>Phone Number: </td>")
.append("<td><strong>")
.append(phNumber)
.append("</strong></td>");
sb.append("</tr>");
sb.append("<br/>");
sb.append("<tr>")
.append("<td>Call Type:</td>")
.append("<td><strong>")
.append(dir)
.append("</strong></td>");
sb.append("</tr>");
sb.append("<br/>");
sb.append("<tr>")
.append("<td>Date & Time:</td>")
.append("<td><strong>")
.append(callDayTime)
.append("</strong></td>");
sb.append("</tr>");
sb.append("<br/>");
sb.append("<tr>")
.append("<td>Call Duration (Seconds):</td>")
.append("<td><strong>")
.append(callDuration)
.append("</strong></td>");
sb.append("</tr>");
sb.append("<br/>");
sb.append("<br/>");
}
sb.append("</table>");
managedCursor.close();
String clLog=sb.toString();
promise.resolve(clLog);
}
catch (IllegalViewOperationException e) { promise.reject(E_LAYOUT_ERROR, e); }
//System.out.println(sb.toString());
// callLogsTextView.setText(Html.fromHtml(sb.toString()));
// WebView webview = new WebView(reactContext.getCurrentActivity());
// webview.loadData(sb.toString(), "text/html", "utf-8");
//Toast.makeText(reactContext, sb.toString(), Toast.LENGTH_LONG).show();
// LayoutInflater inflater = reactContext.getCurrentActivity().getLayoutInflater();
// View layout = inflater.inflate(R.layout.module_layout,
// (ViewGroup) reactContext.getCurrentActivity().findViewById(R.id.custom_toast_container));
//
// ImageView image = (ImageView) layout.findViewById(R.id.image);
// image.setImageResource(R.drawable.android);
// TextView text = (TextView) layout.findViewById(R.id.text);
// text.setText(sb.toString());
//
// Toast toast = new Toast(reactContext.getCurrentActivity());
// toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
// toast.setDuration(Toast.LENGTH_LONG);
// toast.setView(layout);
// toast.show();
}
}
答案 0 :(得分:0)
我明白了。我混淆了承诺和回调代码。 我再次使用了promises,它起作用了。
const log = CallLogAndroid.getCallDetails()。then(function(value){ 的console.log(值);
“。then(function(...”用于解析回调。它不应该被添加,并且必须使用异步函数。使用promises;只需调用该函数就应该返回数据。< / p>