There is no error when gradle. When it is install on the virtual machine, the program cannot run and the following error is displayed. This is the code. This is Android development.
MainActivity.java
package com.example.app;
import java.util.List;
import android.annotation.SuppressLint;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.content.Intent;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import com.esri.arcgisruntime.data.ArcGISFeature;
import com.esri.arcgisruntime.data.FeatureEditResult;
import com.esri.arcgisruntime.loadable.LoadStatus;
import com.esri.arcgisruntime.mapping.Basemap;
import com.esri.arcgisruntime.concurrent.ListenableFuture;
import com.esri.arcgisruntime.layers.ArcGISTiledLayer;
import com.esri.arcgisruntime.data.ServiceFeatureTable;
import com.esri.arcgisruntime.layers.FeatureLayer;
import com.esri.arcgisruntime.mapping.ArcGISMap;
import com.esri.arcgisruntime.mapping.GeoElement;
import com.esri.arcgisruntime.mapping.Viewpoint;
import com.esri.arcgisruntime.mapping.view.Callout;
import com.esri.arcgisruntime.mapping.view.DefaultMapViewOnTouchListener;
import com.esri.arcgisruntime.mapping.view.IdentifyLayerResult;
import com.esri.arcgisruntime.mapping.view.MapView;
import com.google.android.material.snackbar.Snackbar;
import android.app.ProgressDialog;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private MapView mMapView;
private Callout mCallout;
private ArcGISFeature mSelectedArcGISFeature;
private static final String TAG = MainActivity.class.getSimpleName();
private android.graphics.Point mClickPoint;
private Snackbar mSnackbarSuccess;
private Snackbar mSnackbarFailure;
private String mSelectedArcGISFeatureAttributeValue;
private boolean mFeatureUpdated;
private View mCoordinatorLayout;
private ProgressDialog mProgressDialog;
private ServiceFeatureTable mServiceFeatureTable;
private FeatureLayer mFeatureLayer;
@SuppressLint("ClickableViewAccessibility")
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mMapView = findViewById(R.id.mapView);
String url = "http://map.geoq.cn/arcgis/rest/services/ChinaOnlineCommunity/MapServer";
ArcGISTiledLayer arcGISTiledLayer = new ArcGISTiledLayer(url);
Basemap basemap = new Basemap(arcGISTiledLayer);
ArcGISMap arcGISMap = new ArcGISMap(basemap);
mCallout = mMapView.getCallout();
ServiceFeatureTable mServiceFeatureTable = new ServiceFeatureTable("http://192.168.1.103:6080/arcgis/rest/services/huda1/MapServer/0");
FeatureLayer featureLayer = new FeatureLayer(mServiceFeatureTable);
arcGISMap.getOperationalLayers().add(featureLayer);
mFeatureLayer.setOpacity(0.8f);*/
mMapView.setMap(arcGISMap);
mMapView.setViewpoint(new Viewpoint(30.577421, 114.331955, 10000));
//set an on touch listener to listen for click events
// set an on touch listener to listen for click events
mMapView.setOnTouchListener(new DefaultMapViewOnTouchListener(this, mMapView) {
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
// get the point that was clicked and convert it to a point in map coordinates
mClickPoint = new android.graphics.Point((int) e.getX(), (int) e.getY());
// clear any previous selection
mFeatureLayer.clearSelection();
mSelectedArcGISFeature = null;
mCallout.dismiss();
// identify the GeoElements in the given layer
final ListenableFuture<IdentifyLayerResult> identifyFuture = mMapView
.identifyLayerAsync(mFeatureLayer, mClickPoint, 5, false, 1);
// add done loading listener to fire when the selection returns
identifyFuture.addDoneListener(() -> {
try {
// call get on the future to get the result
IdentifyLayerResult layerResult = identifyFuture.get();
List<GeoElement> resultGeoElements = layerResult.getElements();
if (!resultGeoElements.isEmpty()) {
if (resultGeoElements.get(0) instanceof ArcGISFeature) {
mSelectedArcGISFeature = (ArcGISFeature) resultGeoElements.get(0);
// highlight the selected feature
mFeatureLayer.selectFeature(mSelectedArcGISFeature);
// show callout with the value for the attribute "typdamage" of the selected feature
mSelectedArcGISFeatureAttributeValue = (String) mSelectedArcGISFeature.getAttributes()
.get("typdamage");
showCallout(mSelectedArcGISFeatureAttributeValue);
Toast.makeText(MainActivity.this, "Tap on the info button to change attribute value",
Toast.LENGTH_SHORT).show();
}
} else {
// none of the features on the map were selected
mCallout.dismiss();
}
} catch (Exception e1) {
Log.e(TAG, "Select feature failed: " + e1.getMessage());
}
});
return super.onSingleTapConfirmed(e);
}
});
mSnackbarSuccess = Snackbar
.make(mCoordinatorLayout, "Feature successfully updated", Snackbar.LENGTH_LONG)
.setAction("UNDO", view -> {
String snackBarText = updateAttributes(mSelectedArcGISFeatureAttributeValue) ?
"Feature is restored!" :
"Feature restore failed!";
Snackbar snackbar1 = Snackbar.make(mCoordinatorLayout, snackBarText, Snackbar.LENGTH_SHORT);
snackbar1.show();
});
mSnackbarFailure = Snackbar.make(mCoordinatorLayout, "Feature update failed", Snackbar.LENGTH_LONG);
}
/**
* Function to read the result from newly created activity
*/
@Override
protected void onActivityResult(int requestCode,
int resultCode, final Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == 100) {
// display progress dialog while updating attribute callout
mProgressDialog.show();
updateAttributes(data.getStringExtra("typdamage"));
}
}
/**
* Applies changes to the feature, Service Feature Table, and server.
*/
private boolean updateAttributes(final String typeDamage) {
// load the selected feature
mSelectedArcGISFeature.loadAsync();
// update the selected feature
mSelectedArcGISFeature.addDoneLoadingListener(() -> {
if (mSelectedArcGISFeature.getLoadStatus() == LoadStatus.FAILED_TO_LOAD) {
Log.e(TAG, "Error while loading feature");
}
// update the Attributes map with the new selected value for "typdamage"
mSelectedArcGISFeature.getAttributes().put("typdamage", typeDamage);
try {
// update feature in the feature table
ListenableFuture<Void> mapViewResult = mServiceFeatureTable.updateFeatureAsync(mSelectedArcGISFeature);
/*mServiceFeatureTable.updateFeatureAsync(mSelectedArcGISFeature).addDoneListener(new Runnable() {*/
mapViewResult.addDoneListener(() -> {
// apply change to the server
final ListenableFuture<List<FeatureEditResult>> serverResult = mServiceFeatureTable.applyEditsAsync();
serverResult.addDoneListener(() -> {
try {
// check if server result successful
List<FeatureEditResult> edits = serverResult.get();
if (!edits.isEmpty()) {
if (!edits.get(0).hasCompletedWithErrors()) {
Log.e(TAG, "Feature successfully updated");
mSnackbarSuccess.show();
mFeatureUpdated = true;
}
} else {
Log.e(TAG, "The attribute type was not changed");
mSnackbarFailure.show();
mFeatureUpdated = false;
}
if (mProgressDialog.isShowing()) {
mProgressDialog.dismiss();
// display the callout with the updated value
showCallout((String) mSelectedArcGISFeature.getAttributes().get("typdamage"));
}
} catch (Exception e) {
Log.e(TAG, "applying changes to the server failed: " + e.getMessage());
}
});
});
} catch (Exception e) {
Log.e(TAG, "updating feature in the feature table failed: " + e.getMessage());
}
});
return mFeatureUpdated;
}
/**
* Displays Callout
*
* @param title the text to show in the Callout
*/
private void showCallout(String title) {
// create a text view for the callout
RelativeLayout calloutLayout = new RelativeLayout(getApplicationContext());
TextView calloutContent = new TextView(getApplicationContext());
calloutContent.setId(R.id.textview);
calloutContent.setTextColor(Color.BLACK);
calloutContent.setTextSize(18);
calloutContent.setPadding(0, 10, 10, 0);
calloutContent.setText(title);
RelativeLayout.LayoutParams relativeParams = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
relativeParams.addRule(RelativeLayout.RIGHT_OF, calloutContent.getId());
// create image view for the callout
ImageView imageView = new ImageView(getApplicationContext());
imageView
.setImageDrawable(ContextCompat.getDrawable(getApplicationContext(), R.drawable.ic_info_outline_black_18dp));
imageView.setLayoutParams(relativeParams);
imageView.setOnClickListener(new ImageViewOnclickListener());
calloutLayout.addView(calloutContent);
calloutLayout.addView(imageView);
mCallout.setGeoElement(mSelectedArcGISFeature, null);
mCallout.setContent(calloutLayout);
mCallout.show();
}
@Override
protected void onPause() {
mMapView.pause();
super.onPause();
}
@Override
protected void onResume() {
super.onResume();
mMapView.resume();
}
@Override
protected void onDestroy() {
mMapView.dispose();
super.onDestroy();
}
/**
* Defines the listener for the ImageView clicks
*/
private class ImageViewOnclickListener implements View.OnClickListener {
@Override public void onClick(View v) {
Intent myIntent = new Intent(MainActivity.this, DamageTypesListActivity.class);
startActivityForResult(myIntent, 100);
}
}
}
DamageTypesListActivity.java
package com.example.app;
import android.content.Intent;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
/**
* Displays the Damage type options in a ListView.
*/
public class DamageTypesListActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.damage_types_listview);
final String[] damageTypes = getResources().getStringArray(R.array.damage_types);
ListView listView = (ListView) findViewById(R.id.listview);
listView.setAdapter(new ArrayAdapter<>(this, R.layout.damage_types, damageTypes));
listView.setTextFilterEnabled(true);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Intent myIntent = new Intent();
myIntent.putExtra("typdamage", damageTypes[position]); //Optional parameters
setResult(100, myIntent);
finish();
}
});
}
@Override
public void onBackPressed() {
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.app">
<uses-permission android:name="android.permission.INTERNET" />
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
<application
android:allowBackup="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.DisplayAMapJava">
<activity
android:name=".MainActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".DamageTypesListActivity"
android:label="@string/select_damage_Type">
</activity>
</application>
</manifest>
strings.xml
<resources>
<string name="app_name">Display a map java</string>
<string name="select_damage_Type">"Select new damage type"</string>
<!-- Progress dialog messages -->
<string name="progress_title">Updating attribute type</string>
<string name="progress_message">Please wait…</string>
<!-- Sample Strings -->
<string name="sample_service_url">https://sampleserver6.arcgisonline.com/arcgis/rest/services/DamageAssessment/FeatureServer/0</string>
<string-array name="damage_types">
<item>Destroyed</item>
<item>Major</item>
<item>Minor</item>
<item>Affected</item>
<item>Inaccessible</item>
</string-array>
</resources>
below is logcat message
AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.app, PID: 21571
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.app/com.example.app.MainActivity}: java.lang.IllegalArgumentException: No suitable parent found from the given view. Please provide a valid view.
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3270)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Caused by: java.lang.IllegalArgumentException: No suitable parent found from the given view. Please provide a valid view.
at com.google.android.material.snackbar.Snackbar.make(Snackbar.java:158)
at com.example.app.MainActivity.onCreate(MainActivity.java:137)
at android.app.Activity.performCreate(Activity.java:7802)
at android.app.Activity.performCreate(Activity.java:7791)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1299)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)