Я новичок ie в Android Программирование (очень мало знаю о Android программировании). Я пытаюсь читать и кодировать проект в книге, но это старый проект, и большинство зависимостей (Android Studio, SDK, Google Maps, ...) устарели. Я пытаюсь перенести проект на более новую версию, но все еще возникают некоторые проблемы, и программа не запускается.
Здесь находится файл MapsActivity. java, большая часть которого посвящена отображению точки интереса ( POI) и показать карту с помощью Google Maps:
package hitlexamples.happywalk.activities;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Handler;
import android.os.IBinder;
import android.os.Bundle;
import android.os.Looper;
import android.support.v4.app.FragmentActivity;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import java.util.ArrayList;
import java.util.Map;
import hitlexamples.happywalk.R;
import hitlexamples.happywalk.cluster.GeoClusterer;
import hitlexamples.happywalk.cluster.GeoItem;
import hitlexamples.happywalk.service.HappyWalkService;
import hitlexamples.happywalk.tasks.ThreadGetPoi;
import hitlexamples.happywalk.utilities.GlobalVariables;
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {
/* ------------ DEVELOPMENT NOTES ----------------------
- TODO: Fix for devices with low DPI
*/
private GoogleMap mMap; // Might be null if Google Play services APK is not available.
private Handler uiHandler; //handler used by other classes to post tasks to the Ui Thread
private Marker userMarker;
private HappyWalkService hWService;
/** This list contains all available POIs fetched at activity start **/
private ArrayList<GeoItem> geoItems = new ArrayList<GeoItem>();
private GeoClusterer clusterer;
//Thread responsible for fetching POIs
private Thread getpoi;
//workflow variables
private int requestCode = 99;
// GETS AND SETS ------------------------------
public void setGeoItems(ArrayList<GeoItem> geoItems) {
this.geoItems = geoItems;
}
public Handler getUiHandler() {
return uiHandler;
}
public GoogleMap getmMap() {
return mMap;
}
// --------------------------------------------
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
uiHandler = new Handler(Looper.getMainLooper());
//initialize getpoi as an empty thread; will be replaced when necessary.
getpoi = new Thread();
//(Re)start our service.
Intent startHWService = new Intent(this, HappyWalkService.class);
startService(startHWService);
initializeMapComponents();
}
private ServiceConnection hwConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
/*
This is called when the connection with the service has been established, giving us a service object we can use to interact with the service. Because we have bound to a explicit service that we know is running in our own process, we can cast its IBinder to a concrete class and directly access it.
*/
hWService = ((HappyWalkService.HappyWalkBinder)service).getService(MapsActivity.this);
/* Now we check from where this activity is being initiated from */
if (requestCode == GlobalVariables.AREQ_POI_DESCRIPTION_REQUEST) {
/* if we come from POI description, we do nothing.
* The camera should already be focused on the appropriate POI*/
//revert requestCode
requestCode = 99;
}
else {
LatLng position;
//If our service was previously running, let us focus the camera on the user's current position.
if((position = hWService.getHwLocationListener().getActualposition()) !=null) {
updateUserMarkerPosition(position);
focusCameraOnPosition(position);
}
//if not, let us focus our camera onto the last known position
else if ((position = hWService.getHwLocationListener().
getLastKnownPositionFromSharedPrefs()) != null){
focusCameraOnPosition(position);
}
}
}
public void onServiceDisconnected(ComponentName className) {
// This is called when the connection with the service has been
// unexpectedly disconnected -- that is, its process crashed.
// Because it is running in our same process, we should never
// see this happen.
hWService = null;
}
};
private void initializeMapComponents() {
setUpMapIfNeeded();
// Initialize the clusterer
float screenDensity = this.getResources().getDisplayMetrics().density;
clusterer = new GeoClusterer(this, screenDensity, mMap.getCameraPosition().target);
GeoClusterer.ClusterMarkerListener clustLis = clusterer.new ClusterMarkerListener();
GeoClusterer.CameraChangeListener cameraLis = clusterer.new CameraChangeListener();
mMap.setOnMarkerClickListener(clustLis);
mMap.setOnCameraChangeListener(cameraLis);
}
/**
* Here we have to bind to our HappyWalk service again, since we unbinded on pause.
*/
@Override
protected void onResume() {
//check the request code
/* if we are coming from a POI description, ignore this step
otherwise, we will wrongly overwrite the requestCode*/
if (getIntent().getExtras() != null
&& getIntent().getExtras().containsKey(GlobalVariables.BND_EXTRA_REQ_CODE_KEY)
&& requestCode != GlobalVariables.AREQ_POI_DESCRIPTION_REQUEST) {
requestCode = getIntent().getExtras().
getInt(GlobalVariables.BND_EXTRA_REQ_CODE_KEY);
getIntent().removeExtra(GlobalVariables.BND_EXTRA_REQ_CODE_KEY);
}
bindHwService();
super.onResume();
}
/**
* Here we stop the notification requests, the accelerometer collection,
* and the threads that fetch POIs and draw markers.
*/
@Override
protected void onPause() {
getpoi.interrupt();
clusterer.stopMarkerUpdate();
unBindHwService();
super.onPause();
}
/**
* Since this activity is a single instance, this is called whenever we have a new intent
*/
@Override
protected void onNewIntent(Intent intent) {
//update the intent
setIntent(intent);
super.onNewIntent(intent);
}
@Override
public void onMapReady(GoogleMap map) {
// Place your logic here
mMap = map;
map.setIndoorEnabled(true);
map.setBuildingsEnabled(true);
map.getUiSettings().setZoomControlsEnabled(false);
}
// MAP MANIPULATION METHODS ---------------------------
private void setUpMapIfNeeded() {
// Do a null check to confirm that we have not already instantiated the map.
if (mMap == null) {
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
}
/**
Updates the position of the user marker
*/
public void updateUserMarkerPosition(final LatLng position) {
if (userMarker == null) {
userMarker = mMap.addMarker(new MarkerOptions().
//position(position).
//icon(BitmapDescriptorFactory.fromResource(R.drawable.marker_user_position)));
position(position));
}
else {
userMarker.setPosition(position);
}
}
/**
* This function changes the camera to a certain position. It is used by
* the HwLocationListener to change the camera the first time the user changed location
*/
public void focusCameraOnPosition(final LatLng position) {
mMap.getUiSettings().setAllGesturesEnabled(false);
CameraPosition cameraPosition = new CameraPosition.Builder()
.target(position)
.zoom(GlobalVariables.ZOOM_USER_OVERVIEW)
.build();
mMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition),1500,null);
mMap.getUiSettings().setAllGesturesEnabled(true);
}
// ----------------------------------------
// Workflow methods
// ----------------------------------------
/**
* This class starts the thread necessary to request a fresh list of POIs on the App
*/
public void refreshPOIs(double latitude, double longitude) {
while (getpoi.isAlive()) {
getpoi.interrupt();
}
getpoi = new ThreadGetPoi(this, latitude, longitude);
getpoi.start();
}
/**
* Performs clustering of the GeoItems in memory
*/
public void refreshGeoItems() {
/*
refreshing the geoItems is kinda important, so we want it done
ASAP and, thus, don't use our handler.
*/
runOnUiThread(new Runnable() {
public void run() {
clusterer.refreshGeoItems(geoItems);
}
});
}
public void showPOIDetails(String idPoi) {
Intent myIntent = new Intent(getApplicationContext(),
POIDescription.class);
myIntent.putExtra("idPoi", idPoi);
startActivity(myIntent);
requestCode = GlobalVariables.AREQ_POI_DESCRIPTION_REQUEST;
}
/**
* This method binds our MapRouteActivity to the NotificationService
*/
private void bindHwService() {
bindService(new Intent(this, HappyWalkService.class), hwConnection, Context.BIND_AUTO_CREATE);
}
/**
* This method unbinds our MapRouteActivity from the NotificationService
*/
private void unBindHwService() {
unbindService(hwConnection);
hWService = null;
}
/**
* This method is called when the user presses the "Exit" menu option
*/
private void performExit() {
//we don't need to unBind to the service, since we already do that onPause();
stopService(new Intent(this, HappyWalkService.class));
this.finish();
}
// ----------------------------------------
// App Menu
// ----------------------------------------
/**
* This method handles the options Menu
*/
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.map_menu, menu);
return true;
}
/**
* This method handles menu items
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case R.id.menuExit:
performExit();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
Вот ошибка, с которой я столкнулся:
02/02 16:01:23: Launching 'app' on Pixel 3 API 27.
$ adb shell am start -n "hitlexamples.happywalk/hitlexamples.happywalk.activities.MapsActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
Waiting for process to come online...
Connected to process 3972 on device 'Pixel_3_API_27 [emulator-5554]'.
Capturing and displaying logcat messages from application. This behavior can be disabled in the "Logcat output" section of the "Debugger" settings page.
I/FirebaseInitProvider: FirebaseApp initialization unsuccessful
I/zzbx: Making Creator dynamically
I/zygote: The ClassLoaderContext is a special shared library.
I/chatty: uid=10080(hitlexamples.happywalk) identical 1 line
I/zygote: The ClassLoaderContext is a special shared library.
W/zygote: Unsupported class loader
W/zygote: Skipping duplicate class check due to unsupported classloader
I/Google Maps Android API: Google Play services client version: 11020000
I/Google Maps Android API: Google Play services package version: 11580470
I/zygote: Do partial code cache collection, code=30KB, data=15KB
I/zygote: After code cache collection, code=26KB, data=14KB
Increasing code cache capacity to 128KB
I/zygote: Background concurrent copying GC freed 14373(3MB) AllocSpace objects, 1(148KB) LOS objects, 49% free, 1904KB/3MB, paused 12us total 192.833ms
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
Process: hitlexamples.happywalk, PID: 3972
java.lang.RuntimeException: Unable to start activity ComponentInfo{hitlexamples.happywalk/hitlexamples.happywalk.activities.MapsActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'com.google.android.gms.maps.model.CameraPosition com.google.android.gms.maps.GoogleMap.getCameraPosition()' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2778)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2856)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'com.google.android.gms.maps.model.CameraPosition com.google.android.gms.maps.GoogleMap.getCameraPosition()' on a null object reference
at hitlexamples.happywalk.activities.MapsActivity.initializeMapComponents(MapsActivity.java:134)
at hitlexamples.happywalk.activities.MapsActivity.onCreate(MapsActivity.java:87)
at android.app.Activity.performCreate(Activity.java:7009)
at android.app.Activity.performCreate(Activity.java:7000)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1214)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2731)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2856)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
W/DynamiteModule: Local module descriptor class for com.google.android.gms.googlecertificates not found.
W/zygote: Unsupported class loader
W/zygote: Skipping duplicate class check due to unsupported classloader
I/DynamiteModule: Considering local module com.google.android.gms.googlecertificates:0 and remote module com.google.android.gms.googlecertificates:4
Selected remote version of com.google.android.gms.googlecertificates, version >= 4
W/zygote: Unsupported class loader
Skipping duplicate class check due to unsupported classloader
Process 3972 terminated.
Может кто-нибудь помочь мне указать на проблему? Или, если вы считаете, что я предоставляю неадекватную информацию, пожалуйста, сообщите мне, чтобы опубликовать ее дальше. Я очень признателен, так как у меня нет большого опыта, и этот проект - только базовая архитектура для меня, чтобы применить знания в других областях.
Вы можете найти весь проект HappyWalk на этом git сайте. : https://git.dei.uc.pt/dsnunes/happywalk.git
Если кто-нибудь может помочь мне перенести весь проект на более новую версию Android и Карты Google, я очень признателен!
Отредактировано: у меня есть попытался изменить код, как сказал @Evan, но я все еще сталкивался с некоторыми ошибками (он показывает только карты всего мира, пока я ищу область рядом со мной). Может ли кто-нибудь помочь мне с этой ошибкой
02/10 10:10:45: Launching 'app' on Google Pixel 3.
$ adb shell am start -n "hitlexamples.happywalk/hitlexamples.happywalk.activities.MapsActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
Waiting for process to come online...
Connected to process 20363 on device 'google-pixel_3-973X22WD3'.
Capturing and displaying logcat messages from application. This behavior can be disabled in the "Logcat output" section of the "Debugger" settings page.
I/mples.happywal: The ClassLoaderContext is a special shared library.
W/hitlexamples.happywalk: type=1400 audit(0.0:525): avc: denied { read } for comm=45474C20496E6974 name="u:object_r:vendor_default_prop:s0" dev="tmpfs" ino=24252 scontext=u:r:untrusted_app:s0:c181,c256,c512,c768 tcontext=u:object_r:vendor_default_prop:s0 tclass=file permissive=0
E/libc: Access denied finding property "vendor.debug.egl.profiler"
W/mples.happywal: Accessing hidden method Landroid/graphics/drawable/Drawable;->getOpticalInsets()Landroid/graphics/Insets; (light greylist, linking)
Accessing hidden field Landroid/graphics/Insets;->left:I (light greylist, linking)
Accessing hidden field Landroid/graphics/Insets;->right:I (light greylist, linking)
Accessing hidden field Landroid/graphics/Insets;->top:I (light greylist, linking)
Accessing hidden field Landroid/graphics/Insets;->bottom:I (light greylist, linking)
W/mples.happywal: Accessing hidden method Landroid/view/View;->computeFitSystemWindows(Landroid/graphics/Rect;Landroid/graphics/Rect;)Z (light greylist, reflection)
Accessing hidden method Landroid/view/ViewGroup;->makeOptionalFitsSystemWindows()V (light greylist, reflection)
W/mples.happywal: Accessing hidden method Landroid/widget/TextView;->getTextDirectionHeuristic()Landroid/text/TextDirectionHeuristic; (light greylist, linking)
I/zzbz: Making Creator dynamically
W/mples.happywal: Unsupported class loader
W/mples.happywal: Skipping duplicate class check due to unsupported classloader
I/DynamiteModule: Considering local module com.google.android.gms.maps_dynamite:0 and remote module com.google.android.gms.maps_dynamite:222
Selected remote version of com.google.android.gms.maps_dynamite, version >= 222
V/DynamiteModule: Dynamite loader version >= 2, using loadModule2NoCrashUtils
I/DynamiteLoaderV2: [71] Mapsdynamite
W/mples.happywal: Unsupported class loader
W/mples.happywal: Skipping duplicate class check due to unsupported classloader
I/Google Maps Android API: Google Play services client version: 12451000
I/Google Maps Android API: Google Play services package version: 20104028
W/mples.happywal: Accessing hidden field Ljava/nio/Buffer;->address:J (light greylist, reflection)
D/OpenGLRenderer: Skia GL Pipeline
I/Adreno: QUALCOMM build : 3f88ca2, I42f6fe38fb
Build Date : 07/13/18
OpenGL ES Shader Compiler Version: EV031.24.00.00
Local Branch : 50.04
Remote Branch :
Remote Branch :
Reconstruct Branch :
Build Config : S P 4.0.10 AArch64
W/RenderThread: type=1400 audit(0.0:526): avc: denied { read } for name="u:object_r:vendor_default_prop:s0" dev="tmpfs" ino=24252 scontext=u:r:untrusted_app:s0:c181,c256,c512,c768 tcontext=u:object_r:vendor_default_prop:s0 tclass=file permissive=0
E/libc: Access denied finding property "ro.vendor.graphics.memory"
I/Adreno: PFP: 0x016ee170, ME: 0x00000000
I/ConfigStore: android::hardware::configstore::V1_0::ISurfaceFlingerConfigs::hasWideColorDisplay retrieved: 1
android::hardware::configstore::V1_0::ISurfaceFlingerConfigs::hasHDRDisplay retrieved: 1
I/OpenGLRenderer: Initialized EGL, version 1.4
D/OpenGLRenderer: Swap behavior 2
E/libc: Access denied finding property "vendor.gralloc.enable_ahardware_buffer"
W/RenderThread: type=1400 audit(0.0:527): avc: denied { read } for name="u:object_r:vendor_default_prop:s0" dev="tmpfs" ino=24252 scontext=u:r:untrusted_app:s0:c181,c256,c512,c768 tcontext=u:object_r:vendor_default_prop:s0 tclass=file permissive=0
D/NetworkSecurityConfig: No Network Security Config specified, using platform default
W/DynamiteModule: Local module descriptor class for com.google.android.gms.googlecertificates not found.
I/DynamiteModule: Considering local module com.google.android.gms.googlecertificates:0 and remote module com.google.android.gms.googlecertificates:4
Selected remote version of com.google.android.gms.googlecertificates, version >= 4
I/DynamiteLoaderV2: [71] Googlecertificates
W/mples.happywal: Unsupported class loader
W/mples.happywal: Skipping duplicate class check due to unsupported classloader
E/SchedPolicy: set_timerslack_ns write failed: Operation not permitted
Process 20363 terminated.