1

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&#8230;</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) 
James Z
  • 12,209
  • 10
  • 24
  • 44
BarryL
  • 11
  • 2
  • 1
    Does this answer your question? [java.lang.IllegalArgumentException: No suitable parent found from the given view. Please provide a valid view](https://stackoverflow.com/questions/47666685/java-lang-illegalargumentexception-no-suitable-parent-found-from-the-given-view) – deepakchethan Jun 07 '21 at 02:45
  • 1
    You didn't initialize `mCoordinatorLayout` view before using the `SnackBar` – Zain Jun 07 '21 at 02:50
  • How to operate?Please be more specific.Thanks.I've read the article above, and it's not the same problem as his. – BarryL Jun 07 '21 at 08:02

1 Answers1

0

Initialize the CoordinatorLayout (mCoordinatorLayout) before using it in Snackbar.make()

Use findViewById to initialize mCoordinatorLayout mCoordinatorLayout = findViewById(layout_id)