我目前正在开发一款应用,其中一项功能是找到最近的药店。然而,其中一个类PharmacyMapFragment是一个Fragment类,当我尝试调用它时,应用程序崩溃,我收到此错误消息:
' android.content.ActivityNotFoundException:无法找到显式内容 活动课 {com.example.junai.testapp2 / com.example.junai.testapp2.PharmacyMapFragment}; 你有没有在AndroidManifest.xml中声明这个活动?'
我认为你不应该在清单中声明一个Fragment类? 我已经包含了与此问题相关的3个部分的代码。有人可以帮忙吗?
主要活动:
package com.example.junai.testapp2;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.view.View;
import android.widget.Button;
public class MainActivity extends FragmentActivity {
private Button btn_nearest_pharmacy;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn_nearest_pharmacy = (Button) findViewById(R.id.btn_nearest_pharmacy);
btn_nearest_pharmacy.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(MainActivity.this, PharmacyMapFragment.class));
}
});
}
}
PharmacyMapFragment类:
package com.example.junai.testapp2;
import android.app.DialogFragment;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.FragmentActivity;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.location.places.Places;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import org.json.JSONArray;
import org.json.JSONObject;
import java.util.ArrayList;
/**
* Fragment used to display a map of the current location with the nearest pharmacies and other
* nearby pharmacies
*
* References -------------------------------------------------------------------------------------/
* https://github.com/googlemaps/android-samples/blob/master/tutorials/CurrentPlaceDetailsOnMap/app
* /src/main/java/com/example/currentplacedetailsonmap/MapsActivityCurrentPlace.java#
* https://developers.google.com/maps/documentation/android-api/current-place-tutorial
* https://developers.google.com/maps/documentation/android-api/hiding-features
*/
public class PharmacyMapFragment extends Fragment implements OnMapReadyCallback,
GoogleApiClient.OnConnectionFailedListener, GoogleApiClient.ConnectionCallbacks {
//static/default values for settings
private static final String TAG = LogTag.pharmacyLogFragment;
private static final int PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 1;
private static final int DEFAULT_ZOOM = 15;
private static final String KEY_CAMERA_POSITION = "camera_position";
private static final String KEY_LOCATION = "location";
private final LatLng mDefaultLocation = new LatLng(56.463190, -3.038596 );
//used objects
private GoogleMap mMap;
private CameraPosition mCameraPosition;
private GoogleApiClient mGoogleApiClient;
private boolean mLocationPermissionGranted;
private Location mLastKnownLocation;
private ArrayList<Pharmacy> pharmacies = new ArrayList<>();
public PharmacyMapFragment() {}
@Override //generates layout
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_pharmacy_map, container, false);
}
@Override //setup method
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//used for smoother transitions if this is not the first state
if (savedInstanceState != null) {
mLastKnownLocation = savedInstanceState.getParcelable(KEY_LOCATION);
mCameraPosition = savedInstanceState.getParcelable(KEY_CAMERA_POSITION);
}
//set up api client for api calls
mGoogleApiClient = new GoogleApiClient.Builder(getActivity())
.enableAutoManage((FragmentActivity) getActivity(), this)
.addConnectionCallbacks(this)
.addApi(LocationServices.API)
.addApi(Places.GEO_DATA_API)
.addApi(Places.PLACE_DETECTION_API)
.build();
mGoogleApiClient.connect();
}
@Override
public void onMapReady(GoogleMap map) {
mMap = map;
updateLocationUI(); //updates the UI, called first in case of previous sessions
getDeviceLocation(); //get current device location
getPharmaciesFromAPI(); //gets pharmacies from google places search api
}
//Used to update the UI
private void updateLocationUI() {
if (mMap == null) { //if map is null exit method
return;
}
//if we have locations permission set permission to true
if (ContextCompat.checkSelfPermission(getActivity().getApplicationContext(),
android.Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
mLocationPermissionGranted = true;
} else {
ActivityCompat.requestPermissions(getActivity(),
new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},
PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
}
//if we have location permissions update the ui
if (mLocationPermissionGranted) {
mMap.setMyLocationEnabled(true);
mMap.getUiSettings().setMyLocationButtonEnabled(true);
} else {
mMap.setMyLocationEnabled(false);
mMap.getUiSettings().setMyLocationButtonEnabled(false);
mLastKnownLocation = null;
}
}
private void getDeviceLocation() {
//Get location permissions and try to locate current position
if (ContextCompat.checkSelfPermission(getActivity().getApplicationContext(),
android.Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
mLocationPermissionGranted = true;
} else {
ActivityCompat.requestPermissions(getActivity(),
new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},
PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
}
if (mLocationPermissionGranted) {
mLastKnownLocation = LocationServices.FusedLocationApi
.getLastLocation(mGoogleApiClient);
}
// Set the map's camera position to the current location of the device.
if (mCameraPosition != null) {
mMap.moveCamera(CameraUpdateFactory.newCameraPosition(mCameraPosition));
} else if (mLastKnownLocation != null) {
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(
new LatLng(mLastKnownLocation.getLatitude(),
mLastKnownLocation.getLongitude()), DEFAULT_ZOOM));
} else {
Toast.makeText(getActivity(), "Cannot get location", Toast.LENGTH_SHORT).show();
Log.d(TAG, "Current location is null. Using defaults.");
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(mDefaultLocation, DEFAULT_ZOOM));
mMap.getUiSettings().setMyLocationButtonEnabled(false);
}
}
@Override //used when the premission result comes back
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[],
@NonNull int[] grantResults) {
mLocationPermissionGranted = false;
switch (requestCode) {
case PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
mLocationPermissionGranted = true;
}
}
}
updateLocationUI();
}
//gets list of pharmacies as a json object from the api
public void getPharmaciesFromAPI(){
double lat,lng;
if(mLastKnownLocation != null) {
lat = mLastKnownLocation.getLatitude();
lng = mLastKnownLocation.getLongitude();
} else {
lat = mDefaultLocation.latitude;
lng = mDefaultLocation.longitude;
}
// Instantiate the RequestQueue.
RequestQueue queue = Volley.newRequestQueue(getActivity().getApplicationContext());
String API_KEY = getString(R.string.API_KEY);
String url ="https://maps.googleapis.com/maps/api/place/nearbysearch/json?"
+ "location=" + lat + "," + lng + "&rankby=distance&type=pharmacy&key=" + API_KEY;
// Request a string response from the provided URL.
JsonObjectRequest jsObjRequest = new JsonObjectRequest(Request.Method.GET, url, null,
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
parseJSON(response); //parse the json response into pharmacy objects
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.d(TAG, error.toString());
Toast.makeText(getActivity(), "Cannot connect to the internet", Toast.LENGTH_SHORT)
.show();
}
});
// Add the request to the RequestQueue.
queue.add(jsObjRequest);
}
//parses the json
private void parseJSON(JSONObject response){
try {
JSONArray results = response.getJSONArray("results");
pharmacies.clear();
for(int i=0; i<results.length();i++) {
Pharmacy pharmacy = new Pharmacy();
JSONObject current = results.getJSONObject(i);
JSONObject location = current.getJSONObject("geometry").getJSONObject("location");
pharmacy.setLat(location.getDouble("lat"));
pharmacy.setLng(location.getDouble("lng"));
pharmacy.setName(current.getString("name"));
pharmacy.setInfo(current.getString("vicinity"));
pharmacies.add(pharmacy);
}
addMapMarkers(pharmacies);
}catch(Exception e) {
Log.d(TAG, e.toString());
}
}
//adds markers for pharmacies onto the map
private void addMapMarkers(ArrayList<Pharmacy> pharmacies) {
for(int i=0;i<pharmacies.size();i++) {
double lat = pharmacies.get(i).getLat();
double lng = pharmacies.get(i).getLng();
String title = pharmacies.get(i).getName();
if(i==0) {
mMap.addMarker(new MarkerOptions().position(new LatLng(lat,lng)).title(title)
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.
HUE_AZURE)));
} else {
mMap.addMarker(new MarkerOptions().position(new LatLng(lat,lng)).title(title));
}
}
showDialog(pharmacies.get(0));
}
private void showDialog(Pharmacy pharmacy) {
// Supply num input as an argument.
Bundle args = new Bundle();
args.putString("name", pharmacy.getName());
args.putString("info", pharmacy.getInfo());
DialogFragment nearestPharmacy = new NearestPharmacyFragment();
nearestPharmacy.setArguments(args);
nearestPharmacy.show(getFragmentManager().beginTransaction(), "dialog");
}
/*
* API and connection call methods
*/
@Override
public void onSaveInstanceState(Bundle outState) {
if (mMap != null) {
outState.putParcelable(KEY_CAMERA_POSITION, mMap.getCameraPosition());
outState.putParcelable(KEY_LOCATION, mLastKnownLocation);
super.onSaveInstanceState(outState);
}
}
@Override // Build the map.
public void onConnected(Bundle connectionHint) {
FragmentManager manager = getFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
MapFragment fragment = new MapFragment();
transaction.add(R.id.map, fragment);
transaction.commit();
fragment.getMapAsync(this);
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult result) {
Log.d(TAG, "Play services connection failed: ConnectionResult.getErrorCode() = "
+ result.getErrorCode());
}
@Override
public void onConnectionSuspended(int cause) {
Log.d(TAG, "Play services connection suspended. Error code: " + cause);
}
}
fragment_pharmacy_map.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.junai.testapp2.PharmacyMapFragment"
android:name="com.google.android.gms.maps.MapFragment" >
<com.google.android.gms.maps.MapView
class="com.google.android.gms.maps.MapFragment"
android:id="@+id/map"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</FrameLayout>
的AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.junai.testapp2">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<user-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="TestApp2"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="AIzaSyAFK4WLnnx-G4RIV5-3wr2-Pp5LnrkmQhw" />
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".Test">
</activity>
<uses-library android:name="com.google.android.maps" />
</application>
</manifest>
答案 0 :(得分:2)
Intent
用于启动新的 activity
,但您正在使用它来启动 Fragment
,这样是错误。
但别担心,不是什么大不了的事。
在 MainActivity.java 中,
替换此代码
startActivity(new Intent(MainActivity.this, PharmacyMapFragment.class));
这一个
getSupportFragmentManager().beginTransaction().replace(R.id.container, new PharmacyMapFragment()).commit();
确保auto-import
已启用。
这样就可以了。
答案 1 :(得分:1)
老兄,你试图通过使用意图开始片段作为活动。那是错的。您应该按照here所述使用FragmentManager。
答案 2 :(得分:1)
活动可以表示为单个屏幕,片段可以表示为其中的子视图。
您不能直接显示片段,您需要主持人将其附加,也就是说,您需要一个活动来托管您的片段。您可以在活动中放置单个或多个片段,片段将显示在其中。
这里你调用了startActivity,这个方法用于启动一个活动,你传递了一个PharmacyMapFragment,它是一个片段而不是一个活动。因此,它无法查看具有该类型的活动并抛出该错误。
TL; DR
创建一个活动,将PharmacyMapFragment放入其中,将其置于活动的布局中或使用Fragment事务,然后使用该活动的类名调用startActivity
教程:https://developer.android.com/guide/components/fragments.html#Adding