因此我从我的某项服务中收到意图时遇到问题。我一直在寻找问题发生的确切位置,并发现它发生在" TimerService"尝试将意图广播到MainAcivity的片段类。 这是MainActicity类:
package com.exotics.buses;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.location.Location;
import android.location.LocationManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.NetworkInfo.State;
import android.os.Bundle;
import android.os.Handler;
import android.provider.Settings;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
import android.widget.Toast;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.maps.CameraUpdate;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.GoogleMap.OnMapLongClickListener;
import com.google.android.gms.maps.MapView;
import com.google.android.gms.maps.MapsInitializer;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
@SuppressLint("NewApi")
public class MainActivity extends ActionBarActivity implements
NavigationDrawerFragment.NavigationDrawerCallbacks {
/**
* Fragment managing the behaviors, interactions and presentation of the
* navigation drawer.
*/
private static NavigationDrawerFragment mNavigationDrawerFragment;
/**
* Used to store the last screen title. For use in
* {@link #restoreActionBar()}.
*/
private static CharSequence mTitle;
/**
* Used to switch fragments when clicking on search icon on action bar.
*/
private static FragmentManager fManager;
/**
* Used to handle search EditText.
*/
private static EditText searchEditText;
/**
* Reference to "PlaceholderFragment" used to access current section number
* and to store all fragments numbers.
*/
private static PlaceholderFragment fragment;
/**
* Used to get the current section number.
*/
private static final String ARG_SECTION_NUMBER = "section_number";
/**
* Used to check for GPS and network settings.
*/
private LocationManager mLocationManager;
private ConnectivityManager mConnectivityManager;
private static boolean locationEnabled = false;
private static boolean networkEnabled = false;
/**
* Used to update the icon on the action bar.
*/
private static MenuItem actionbarMenu;
/**
* Used to manage keyboard (Show or Hide).
*/
private static InputMethodManager keyboardInput;
/**
* Used to manage UpdateService.
*/
private static Intent mServiceIntent;
private static String dataUrl = "com.exotics.buses.DATAURL";
/**
* Used to manage TimerService.
*/
static Intent timerIntent;
long timeSwapBuff = 0L;
long updatedTime = 0L;
static BroadcastReceiver broadcastReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mNavigationDrawerFragment = (NavigationDrawerFragment) getSupportFragmentManager()
.findFragmentById(R.id.navigation_drawer);
mTitle = getTitle();
// Set up the drawer.
mNavigationDrawerFragment.setUp(R.id.navigation_drawer,
(DrawerLayout) findViewById(R.id.drawer_layout));
networkEnabled = isNetworkConnectionAvailable();
locationEnabled = isLocationServicesAvailable();
if (!networkEnabled)
Toast.makeText(getApplicationContext(),
"Internet connection not available.", Toast.LENGTH_LONG)
.show();
keyboardInput = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
/*
* Creates a new Intent to start the RSSPullService IntentService.
* Passes a URI in the Intent's "data" field.
*/
// mServiceIntent = new Intent(this, UpdateService.class);
}
@Override
public void onNavigationDrawerItemSelected(int position) {
// update the main content by replacing fragments
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager
.beginTransaction()
.replace(R.id.container,
PlaceholderFragment.newInstance(position + 1)).commit();
fManager = getSupportFragmentManager();
}
public void onSectionAttached(int number) {
switch (number) {
case 1:
mTitle = getString(R.string.title_section1);
break;
case 2:
mTitle = getString(R.string.title_section2);
break;
case 3:
mTitle = getString(R.string.title_section3);
break;
}
}
public void restoreActionBar() {
ActionBar actionBar = getSupportActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
actionBar.setDisplayShowTitleEnabled(true);
actionBar.setTitle(mTitle);
if (isHomeSectionPresent())
actionbarMenu.setIcon(R.drawable.ic_search_actionbar);
else
actionbarMenu.setIcon(R.drawable.ic_map_actionbar);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
if (!mNavigationDrawerFragment.isDrawerOpen()) {
// Only show items in the action bar relevant to this screen
// if the drawer is not showing. Otherwise, let the drawer
// decide what to show in the action bar.
getMenuInflater().inflate(R.menu.main, menu);
actionbarMenu = menu.findItem(R.id.action_bar);
restoreActionBar();
return true;
}
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment implements
LocationListener, android.location.LocationListener,
UpdateReceiver.Receiver {
/**
* The fragment argument representing the section number for this
* fragment.
*/
private View rootView;
/**
* Google Maps Variables.
*/
private MapView mMapView;
private GoogleMap mMap;
private Bundle mBundle;
private LocationManager locationManager;
private static final long MIN_TIME = 400;
private static final float MIN_DISTANCE = 1000;
private boolean isMapInitialized = false;
/**
* UpdateReciver manager.
*/
private UpdateReceiver mReceiver;
/**
* Returns a new instance of this fragment for the given section number.
*/
public static PlaceholderFragment newInstance(int sectionNumber) {
fragment = new PlaceholderFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
fragment.setArguments(args);
return fragment;
}
public PlaceholderFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (getArguments().getInt(ARG_SECTION_NUMBER) == 1) {
rootView = inflater.inflate(R.layout.fragment_main, container,
false);
updateView();
if (hasLocation() && hasNetwork())
initializeMap();
return rootView;
}
rootView = inflater.inflate(R.layout.fragment_default, container,
false);
if (keyboardInput != null) {
keyboardInput.toggleSoftInput(
InputMethodManager.HIDE_IMPLICIT_ONLY, 0);
}
return rootView;
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
((MainActivity) activity).onSectionAttached(getArguments().getInt(
ARG_SECTION_NUMBER));
}
/**
* Google Maps Functions.
*/
private void initializeMap() {
locationManager = (LocationManager) getActivity()
.getApplicationContext().getSystemService(
Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, MIN_TIME, MIN_DISTANCE,
this);
// Can also use LocationManager.GPS_PROVIDER and
// LocationManager.PASSIVE_PROVIDER
MapsInitializer.initialize(getActivity());
mMapView = (MapView) rootView.findViewById(R.id.map);
mMapView.onCreate(mBundle);
isMapInitialized = true;
setUpMapIfNeeded(rootView);
}
private void setUpMapIfNeeded(View inflatedView) {
if (mMap == null) {
mMap = ((MapView) inflatedView.findViewById(R.id.map)).getMap();
if (mMap != null) {
setUpMap();
}
}
}
private void setUpMap() {
mMap.setMyLocationEnabled(true);
mMap.setOnMapLongClickListener(new OnMapLongClickListener() {
@Override
public void onMapLongClick(LatLng point) {
mMap.addMarker(new MarkerOptions()
.title("Bus Location")
.icon(BitmapDescriptorFactory
.fromResource(R.drawable.ic_map_marker))
// .anchor(0.0f, 1.0f) // Anchors the marker on the
// // bottom left
.snippet("MARKER TEST").position(point));
}
});
startUpdateService(); // Start UpdateService
startTimerService(); // Start TimerService
}
@Override
public void onResume() {
super.onResume();
if (getArguments().getInt(ARG_SECTION_NUMBER) == 1) {
updateView();
if (isMapInitialized)
mMapView.onResume();
}
}
@Override
public void onPause() {
super.onPause();
if (getArguments().getInt(ARG_SECTION_NUMBER) == 1
&& isMapInitialized)
mMapView.onPause();
}
@Override
public void onDestroy() {
if (getArguments().getInt(ARG_SECTION_NUMBER) == 1
&& isMapInitialized)
mMapView.onDestroy();
super.onDestroy();
}
@Override
public void onLocationChanged(Location location) {
LatLng latLng = new LatLng(location.getLatitude(),
location.getLongitude());
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(
latLng, 15);
mMap.animateCamera(cameraUpdate);
locationManager.removeUpdates(this);
}
private boolean hasLocation() {
return locationEnabled;
}
private boolean hasNetwork() {
return networkEnabled;
}
/**
* Updates the fragment view depending on the availability of location
* services and Internet connection.
*/
private void updateView() {
if (hasNetwork() == false && hasLocation() == true) {
TextView textView = (TextView) rootView
.findViewById(R.id.NetworkLocationText);
Button btn = (Button) rootView.findViewById(R.id.GPSButton);
btn.setVisibility(View.INVISIBLE);
btn = (Button) rootView.findViewById(R.id.NetworkButton);
btn.setVisibility(View.VISIBLE);
textView.setText(getString(R.string.NetworkNotAvailable));
} else if (hasNetwork() == true && hasLocation() == false) {
TextView textView = (TextView) rootView
.findViewById(R.id.NetworkLocationText);
Button btn = (Button) rootView.findViewById(R.id.NetworkButton);
btn.setVisibility(View.INVISIBLE);
btn = (Button) rootView.findViewById(R.id.GPSButton);
btn.setVisibility(View.VISIBLE);
textView.setText(getString(R.string.GPSNotAvailable));
} else if (hasNetwork() && hasLocation()) {
TextView textView = (TextView) rootView
.findViewById(R.id.NetworkLocationText);
textView.setVisibility(View.INVISIBLE);
Button btn = (Button) rootView.findViewById(R.id.NetworkButton);
btn.setVisibility(View.INVISIBLE);
btn = (Button) rootView.findViewById(R.id.GPSButton);
btn.setVisibility(View.INVISIBLE);
}
}
private void startUpdateService() {
/* Starting Update Service */
mReceiver = new UpdateReceiver(new Handler());
mReceiver.setReceiver(this);
mServiceIntent = new Intent(Intent.ACTION_SYNC, null,
getActivity(), UpdateService.class);
/* Send optional extras to Update IntentService */
mServiceIntent.putExtra("url", dataUrl);
mServiceIntent.putExtra("receiver", mReceiver);
mServiceIntent.putExtra("isMapInitialized", isMapInitialized);
getActivity().startService(mServiceIntent);
}
private void startTimerService() {
timerIntent = new Intent(getActivity(), TimerService.class);
getActivity().startService(timerIntent);
getActivity().registerReceiver(broadcastReceiver,
new IntentFilter(TimerService.BROADCAST_ACTION));
broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
updateService(intent);
}
};
}
private void updateService(Intent intent) {
boolean startservice = intent.getBooleanExtra("StratUpdateService",
false);
if (startservice) {
}
startUpdateService(); // Restart Update service with an interval.
}
@Override
public void onReceiveResult(int resultCode, Bundle resultData) {
switch (resultCode) {
case UpdateService.STATUS_RUNNING:
/*
* TODO: show the user that something is running in the
* background (progress bar maybe).
*/
break;
case UpdateService.STATUS_FINISHED:
// TODO: Hide progress bar & extract results from bundle */
boolean doClear = resultData.getBoolean("clear", true);
double[][] results = null;
Object[] objectArray = (Object[]) resultData
.getSerializable("results");
if (objectArray != null) {
results = new double[objectArray.length][];
for (int i = 0; i < objectArray.length; i++) {
results[i] = (double[]) objectArray[i];
}
}
// TODO: Update Map with new results */
if (doClear) {
mMap.clear();
int row = results.length;
for (int i = 0; i < row; i++) {
Log.d("Location", String.valueOf(results[i][0]) + " "
+ String.valueOf(results[i][1]));
LatLng point = new LatLng(results[i][0], results[i][1]);
mMap.addMarker(new MarkerOptions()
.title("Bus Location")
.icon(BitmapDescriptorFactory
.fromResource(R.drawable.ic_map_marker))
.snippet("MARKER TEST").position(point));
}
}
break;
case UpdateService.STATUS_ERROR:
// TODO: Handle the error */
String error = resultData.getString(Intent.EXTRA_TEXT);
Toast.makeText(getActivity(), error, Toast.LENGTH_LONG).show();
break;
}
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
}
// onResume will be used to handle fragment's view widgets
@Override
public void onResume() {
super.onResume();
resetFragment();
fManager = getSupportFragmentManager();
searchEditText = (EditText) findViewById(R.id.search_box);
searchEditText.setOnEditorActionListener(new OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId,
KeyEvent event) {
boolean handled = false;
String searchQuery = "";
if (actionId == EditorInfo.IME_ACTION_SEARCH
|| event.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
searchQuery = String.valueOf(searchEditText.getText());
ServerHandler.pullData(searchQuery);
handled = true;
}
return handled;
}
});
}
// TODO: check this out maybe!
// @Override
// public void onPause(){
// super.onPause();
// unregisterReceiver(broadcastReceiver);
// stopService(timerIntent);
// }
// Focus on search edit box
public static void focusOnSearch(Activity activity) {
if (fragment.getArguments().getInt(ARG_SECTION_NUMBER) == 1) {
searchEditText = (EditText) ((MainActivity) activity)
.findViewById(R.id.search_box);
searchEditText.requestFocus();
if (keyboardInput != null) {
keyboardInput.toggleSoftInput(0,
InputMethodManager.SHOW_IMPLICIT);
}
} else {
fManager.beginTransaction()
.replace(R.id.container, PlaceholderFragment.newInstance(1))
.commit();
mNavigationDrawerFragment = (NavigationDrawerFragment) ((MainActivity) activity)
.getSupportFragmentManager().findFragmentById(
R.id.navigation_drawer);
mTitle = ((MainActivity) activity)
.getString(R.string.title_section1);
actionbarMenu.setIcon(R.drawable.ic_search_actionbar);
}
}
private boolean isNetworkConnectionAvailable() {
mConnectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = mConnectivityManager.getActiveNetworkInfo();
if (info == null)
return false;
State network = info.getState();
return (network == NetworkInfo.State.CONNECTED || network == NetworkInfo.State.CONNECTING);
}
private boolean isLocationServicesAvailable() {
mLocationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
return (mLocationManager
.isProviderEnabled(LocationManager.GPS_PROVIDER));
}
private boolean isHomeSectionPresent() {
if (fragment.getArguments().getInt(ARG_SECTION_NUMBER) == 1)
return true;
else
return false;
}
public void resetFragment() {
// Do rechecks on location services and network state.
networkEnabled = isNetworkConnectionAvailable();
locationEnabled = isLocationServicesAvailable();
// Update the main content by replacing home fragment with it self.
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager
.beginTransaction()
.replace(
R.id.container,
PlaceholderFragment.newInstance(fragment.getArguments()
.getInt(ARG_SECTION_NUMBER))).commit();
fManager = getSupportFragmentManager();
}
// OnClick, refresh fragment.
public void tryAgain(View view) {
resetFragment();
Toast.makeText(getApplicationContext(), "Reset", Toast.LENGTH_SHORT)
.show();
}
// OnClick, Call GPS settings activity.
public void locationSettings(View view) {
Intent settingsIntent = new Intent(
Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(settingsIntent);
}
}
这是TimerService:
package com.exotics.buses;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
public class TimerService extends Service {
private Intent intent;
public static final String BROADCAST_ACTION = "com.exotics.buses.MainActivity.PlaceholderFragment";
private static final String TAG = "TimerService";
private Handler handler = new Handler();
long timeInMilliseconds = 0L;
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "Service Started!");
intent = new Intent(BROADCAST_ACTION);
handler.removeCallbacks(setupUpdateService);
handler.postDelayed(setupUpdateService, 10000); // 10 second
}
private Runnable setupUpdateService = new Runnable() {
public void run() {
Log.d(TAG, "Runnable Started!");
startUpdateService();
handler.postDelayed(this, 10000); // 10 seconds
}
};
private void startUpdateService() {
intent.putExtra("StratUpdateService", true);
Log.d(TAG, "Broadcastting!");
sendBroadcast(intent);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy!");
handler.removeCallbacks(setupUpdateService);
}
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
}
这是错误:
03-11 18:08:13.738: E/AndroidRuntime(27035): FATAL EXCEPTION: main
03-11 18:08:13.738: E/AndroidRuntime(27035): java.lang.RuntimeException: Error receiving broadcast Intent { act=com.exotics.buses.MainActivity.PlaceholderFragment flg=0x10 (has extras) } in com.exotics.buses.MainActivity$PlaceholderFragment$2@413ca660
03-11 18:08:13.738: E/AndroidRuntime(27035): at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:768)
03-11 18:08:13.738: E/AndroidRuntime(27035): at android.os.Handler.handleCallback(Handler.java:725)
03-11 18:08:13.738: E/AndroidRuntime(27035): at android.os.Handler.dispatchMessage(Handler.java:92)
03-11 18:08:13.738: E/AndroidRuntime(27035): at android.os.Looper.loop(Looper.java:137)
03-11 18:08:13.738: E/AndroidRuntime(27035): at android.app.ActivityThread.main(ActivityThread.java:5227)
03-11 18:08:13.738: E/AndroidRuntime(27035): at java.lang.reflect.Method.invokeNative(Native Method)
03-11 18:08:13.738: E/AndroidRuntime(27035): at java.lang.reflect.Method.invoke(Method.java:511)
03-11 18:08:13.738: E/AndroidRuntime(27035): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:795)
03-11 18:08:13.738: E/AndroidRuntime(27035): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:562)
03-11 18:08:13.738: E/AndroidRuntime(27035): at dalvik.system.NativeStart.main(Native Method)
03-11 18:08:13.738: E/AndroidRuntime(27035): Caused by: java.lang.NullPointerException
03-11 18:08:13.738: E/AndroidRuntime(27035): at android.content.ComponentName.<init>(ComponentName.java:75)
03-11 18:08:13.738: E/AndroidRuntime(27035): at android.content.Intent.<init>(Intent.java:3588)
03-11 18:08:13.738: E/AndroidRuntime(27035): at com.exotics.buses.MainActivity$PlaceholderFragment.startUpdateService(MainActivity.java:405)
03-11 18:08:13.738: E/AndroidRuntime(27035): at com.exotics.buses.MainActivity$PlaceholderFragment.updateService(MainActivity.java:436)
03-11 18:08:13.738: E/AndroidRuntime(27035): at com.exotics.buses.MainActivity$PlaceholderFragment.access$1(MainActivity.java:430)
03-11 18:08:13.738: E/AndroidRuntime(27035): at com.exotics.buses.MainActivity$PlaceholderFragment$2.onReceive(MainActivity.java:425)
03-11 18:08:13.738: E/AndroidRuntime(27035): at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:758)
03-11 18:08:13.738: E/AndroidRuntime(27035): ... 9 more
那么请问我做错了什么?还有更好的方法来解决这个问题吗?
答案 0 :(得分:0)
logcat的这一行:
at com.exotics.buses.MainActivity $ PlaceholderFragment.startUpdateService(MainActivity.java:405)
指向程序中您在Intent上调用遇到NullPointerException的方法的行。弄清楚它是什么指针以及为什么它是null。
您可以先在该行上设置一个断点并查看该调用的参数。
仅供参考:我通过查找“引发”消息找到了logcat行,然后从那里向下扫描,直到我到达你代码中的最后一个电话,而不是Android的电话。
答案 1 :(得分:0)
感谢戴尔威尔逊,我知道在哪里寻找问题。所以这是解决方案:
首先,我声明了一个私有静态上下文,它代表&#34; MainActivity&#34;
的上下文private static Context mainActivityContext;
接下来在MainActivity的onCreate中初始化了上下文变量
mainActivityContext = MainActivity.this;
然后我替换了这个
mServiceIntent = new Intent(Intent.ACTION_SYNC, null,
getActivity(), UpdateService.class);
有了这个
mServiceIntent = new Intent(Intent.ACTION_SYNC, null,
mainActivityContext, UpdateService.class);
和这个
getActivity().startService(mServiceIntent);
有了这个
mainActivityContext.startService(mServiceIntent);
那是怎么回事?显然getActivity()返回null!这就是NullPointerException。为什么呢?我不知道:D但它现在就像一个魅力:)
我希望这可以帮助有类似问题的人:)