用户运动检测应用程序不断崩溃
Posted
技术标签:
【中文标题】用户运动检测应用程序不断崩溃【英文标题】:User Motion Detection App keeps on crashing 【发布时间】:2014-09-02 14:40:33 【问题描述】:我一直在开发这个应用程序。 它只是不会执行。 每次都崩溃。请帮忙。
androidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.androidrecipes.usermotionactivity"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="18" />
<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<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>
<service android:name="com.androidrecipes.usermotionactivity.UserMotionService" />
</application>
</manifest>
UserMotionService.java
package com.androidrecipes.usermotionactivity;
import com.google.android.gms.location.ActivityRecognitionResult;
import com.google.android.gms.location.DetectedActivity;
import android.app.IntentService;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;
public class UserMotionService extends IntentService
private static final String TAG = "UserMotionService";
/*
* Callback interface for detected activity type changes
*/
public interface OnActivityChangedListener
public void onUserActivityChanged(int bestChoice, int bestConfidence,
ActivityRecognitionResult newActivity);
/* Last detected activity type */
private DetectedActivity mLastKnownActivity;
/*
* Marshals requests from the background thread so the callbacks
* can be made on the main (UI) thread.
*/
private CallbackHandler mHandler;
private static class CallbackHandler extends Handler
/* Callback for activity changes */
private OnActivityChangedListener mCallback;
public void setCallback(OnActivityChangedListener callback)
mCallback = callback;
@Override
public void handleMessage(Message msg)
if (mCallback != null)
//Read payload data out of the message and fire callback
ActivityRecognitionResult newActivity = (ActivityRecognitionResult) msg.obj;
mCallback.onUserActivityChanged(msg.arg1, msg.arg2, newActivity);
public UserMotionService()
//String is used to name the background thread created
super("UserMotionService");
mHandler = new CallbackHandler();
public void setOnActivityChangedListener(OnActivityChangedListener listener)
mHandler.setCallback(listener);
@Override
public void onDestroy()
super.onDestroy();
Log.w(TAG, "Service is stopping...");
/*
* Incoming action events from the framework will come
* in here. This is called on a background thread, so
* we can do long processing here if we wish.
*/
@Override
protected void onHandleIntent(Intent intent)
if (ActivityRecognitionResult.hasResult(intent))
//Extract the result from the Intent
ActivityRecognitionResult result =
ActivityRecognitionResult.extractResult(intent);
DetectedActivity activity = result.getMostProbableActivity();
Log.v(TAG, "New User Activity Event");
//If the highest probability is UNKNOWN, but the confidence is low,
// check if another exists and select it instead
if (activity.getType() == DetectedActivity.UNKNOWN
&& activity.getConfidence() < 60
&& result.getProbableActivities().size() > 1)
//Select the next probable element
activity = result.getProbableActivities().get(1);
//On a change in activity, alert the callback
if (mLastKnownActivity == null
|| mLastKnownActivity.getType() != activity.getType()
|| mLastKnownActivity.getConfidence() != activity.getConfidence())
//Pass the results to the main thread inside a Message
Message msg = Message.obtain(null,
0, //what
activity.getType(), //arg1
activity.getConfidence(), //arg2
result);
mHandler.sendMessage(msg);
mLastKnownActivity = activity;
/*
* This is called when the Activity wants to bind to the
* service. We have to provide a wrapper around this instance
* to pass it back.
*/
@Override
public IBinder onBind(Intent intent)
return mBinder;
/*
* This is a simple wrapper that we can pass to the Activity
* to allow it direct access to this service.
*/
private LocalBinder mBinder = new LocalBinder();
public class LocalBinder extends Binder
public UserMotionService getService()
return UserMotionService.this;
/*
* Utility to get a good display name for each state
*/
public static String getActivityName(DetectedActivity activity)
switch(activity.getType())
case DetectedActivity.IN_VEHICLE:
return "Driving";
case DetectedActivity.ON_BICYCLE:
return "Biking";
case DetectedActivity.ON_FOOT:
return "Walking";
case DetectedActivity.STILL:
return "Not Moving";
case DetectedActivity.TILTING:
return "Tilting";
case DetectedActivity.UNKNOWN:
default:
return "No Clue";
MainActivity.java
package com.androidrecipes.usermotionactivity;
import com.androidrecipes.usermotionactivity.UserMotionService.LocalBinder;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesClient;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.location.ActivityRecognitionClient;
import com.google.android.gms.location.ActivityRecognitionResult;
import com.google.android.gms.location.DetectedActivity;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.text.format.DateFormat;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity implements
ServiceConnection,
UserMotionService.OnActivityChangedListener,
GooglePlayServicesClient.ConnectionCallbacks,
GooglePlayServicesClient.OnConnectionFailedListener
private static final String TAG = "UserActivity";
private Intent mServiceIntent;
private PendingIntent mCallbackIntent;
private UserMotionService mService;
private ActivityRecognitionClient mRecognitionClient;
//Custom list adapter to display our results
private ActivityAdapter mListAdapter;
private View mBlockingView;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBlockingView = findViewById(R.id.blocker);
//Construct a simple list adapter that will display all the
// incoming activity change events from the service.
ListView list = (ListView) findViewById(R.id.list);
mListAdapter = new ActivityAdapter(this);
list.setAdapter(mListAdapter);
//When the list is clicked, display all the probable activities
list.setOnItemClickListener(new AdapterView.OnItemClickListener()
@Override
public void onItemClick(AdapterView<?> parent, View v, int position, long id)
showDetails(mListAdapter.getItem(position));
);
//Check if Google Play Services is up to date.
switch (GooglePlayServicesUtil.isGooglePlayServicesAvailable(this))
case ConnectionResult.SUCCESS:
//Do nothing, move on
break;
case ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED:
Toast.makeText(this,
"Activity service requires an update, please open Google Play.",
Toast.LENGTH_SHORT).show();
finish();
return;
default:
Toast.makeText(this,
"Activity service is not available on this device.",
Toast.LENGTH_SHORT).show();
finish();
return;
//Create a client instance for talking to Google Services
mRecognitionClient = new ActivityRecognitionClient(this, this, this);
//Create an Intent to bind to the service
mServiceIntent = new Intent(this, UserMotionService.class);
//Create a PendingIntent that Google Services will use for callbacks
mCallbackIntent = PendingIntent.getService(this, 0,
mServiceIntent, PendingIntent.FLAG_UPDATE_CURRENT);
@Override
protected void onResume()
super.onResume();
//Connect to Google Services and our Service
mRecognitionClient.connect();
bindService(mServiceIntent, this, BIND_AUTO_CREATE);
@Override
protected void onPause()
super.onPause();
//Disconnect from all services
mRecognitionClient.removeActivityUpdates(mCallbackIntent);
mRecognitionClient.disconnect();
disconnectService();
unbindService(this);
/** ServiceConnection Methods */
public void onServiceConnected(ComponentName name, IBinder service)
//Attach ourselves to our Service as a callback for events
mService = ((LocalBinder) service).getService();
mService.setOnActivityChangedListener(this);
@Override
public void onServiceDisconnected(ComponentName name)
disconnectService();
private void disconnectService()
if (mService != null)
mService.setOnActivityChangedListener(null);
mService = null;
/** Google Services Connection Callbacks */
@Override
public void onConnected(Bundle connectionHint)
//We must wait until the services are connected
// to request any updates.
mRecognitionClient.requestActivityUpdates(5000, mCallbackIntent);
@Override
public void onDisconnected()
Log.w(TAG, "Google Services Disconnected");
@Override
public void onConnectionFailed(ConnectionResult result)
Log.w(TAG, "Google Services Connection Failure");
/** OnActivityChangedListener Methods */
@Override
public void onUserActivityChanged(int bestChoice, int bestConfidence,
ActivityRecognitionResult newActivity)
//Add latest event to the list
mListAdapter.add(newActivity);
mListAdapter.notifyDataSetChanged();
//Determine user action based on our custom algorithm
switch (bestChoice)
case DetectedActivity.IN_VEHICLE:
case DetectedActivity.ON_BICYCLE:
mBlockingView.setVisibility(View.VISIBLE);
break;
case DetectedActivity.ON_FOOT:
case DetectedActivity.STILL:
mBlockingView.setVisibility(View.GONE);
break;
default:
//Ignore other states
break;
/*
* Utility that builds a simple Toast with all the probable
* activity choices with their confidence values
*/
private void showDetails(ActivityRecognitionResult activity)
StringBuilder sb = new StringBuilder();
sb.append("Details:");
for(DetectedActivity element : activity.getProbableActivities())
sb.append("\n"+UserMotionService.getActivityName(element)
+ ", " + element.getConfidence() + "% sure");
Toast.makeText(this, sb.toString(), Toast.LENGTH_SHORT).show();
/*
* ListAdapter to display each activity result we receive from the service
*/
private static class ActivityAdapter extends ArrayAdapter<ActivityRecognitionResult>
public ActivityAdapter(Context context)
super(context, android.R.layout.simple_list_item_1);
@Override
public View getView(int position, View convertView, ViewGroup parent)
if (convertView == null)
convertView = LayoutInflater.from(getContext())
.inflate(android.R.layout.simple_list_item_1, parent, false);
//Display the most probable activity with its confidence in the list
TextView tv = (TextView) convertView;
ActivityRecognitionResult result = getItem(position);
DetectedActivity newActivity = result.getMostProbableActivity();
String entry = DateFormat.format("hh:mm:ss", result.getTime())
+ ": " + UserMotionService.getActivityName(newActivity) + ", "
+ newActivity.getConfidence() + "% confidence";
tv.setText(entry);
return convertView;
Logcat:
09-02 10:29:16.635: D/dalvikvm(1867): GC_FOR_ALLOC freed 42K, 4% free 2901K/3008K, paused 151ms, total 152ms
09-02 10:29:16.635: I/dalvikvm-heap(1867): Grow heap (frag case) to 3.500MB for 635808-byte allocation
09-02 10:29:16.755: D/dalvikvm(1867): GC_FOR_ALLOC freed 2K, 4% free 3520K/3632K, paused 117ms, total 117ms
09-02 10:29:17.495: D/AndroidRuntime(1867): Shutting down VM
09-02 10:29:17.535: W/dalvikvm(1867): threadid=1: thread exiting with uncaught exception (group=0xb2d74b20)
09-02 10:29:17.675: E/AndroidRuntime(1867): FATAL EXCEPTION: main
09-02 10:29:17.675: E/AndroidRuntime(1867): Process: com.androidrecipes.usermotionactivity, PID: 1867
09-02 10:29:17.675: E/AndroidRuntime(1867): java.lang.RuntimeException: Unable to start activity ComponentInfocom.androidrecipes.usermotionactivity/com.androidrecipes.usermotionactivity.MainActivity: java.lang.IllegalStateException: A required meta-data tag in your app's AndroidManifest.xml does not exist. You must have the following declaration within the <application> element: <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
09-02 10:29:17.675: E/AndroidRuntime(1867): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2195)
09-02 10:29:17.675: E/AndroidRuntime(1867): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
09-02 10:29:17.675: E/AndroidRuntime(1867): at android.app.ActivityThread.access$800(ActivityThread.java:135)
09-02 10:29:17.675: E/AndroidRuntime(1867): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
09-02 10:29:17.675: E/AndroidRuntime(1867): at android.os.Handler.dispatchMessage(Handler.java:102)
09-02 10:29:17.675: E/AndroidRuntime(1867): at android.os.Looper.loop(Looper.java:136)
09-02 10:29:17.675: E/AndroidRuntime(1867): at android.app.ActivityThread.main(ActivityThread.java:5017)
09-02 10:29:17.675: E/AndroidRuntime(1867): at java.lang.reflect.Method.invokeNative(Native Method)
09-02 10:29:17.675: E/AndroidRuntime(1867): at java.lang.reflect.Method.invoke(Method.java:515)
09-02 10:29:17.675: E/AndroidRuntime(1867): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
09-02 10:29:17.675: E/AndroidRuntime(1867): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
09-02 10:29:17.675: E/AndroidRuntime(1867): at dalvik.system.NativeStart.main(Native Method)
09-02 10:29:17.675: E/AndroidRuntime(1867): Caused by: java.lang.IllegalStateException: A required meta-data tag in your app's AndroidManifest.xml does not exist. You must have the following declaration within the <application> element: <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
09-02 10:29:17.675: E/AndroidRuntime(1867): at com.google.android.gms.common.GooglePlayServicesUtil.A(Unknown Source)
09-02 10:29:17.675: E/AndroidRuntime(1867): at com.google.android.gms.common.GooglePlayServicesUtil.isGooglePlayServicesAvailable(Unknown Source)
09-02 10:29:17.675: E/AndroidRuntime(1867): at com.androidrecipes.usermotionactivity.MainActivity.onCreate(MainActivity.java:69)
09-02 10:29:17.675: E/AndroidRuntime(1867): at android.app.Activity.performCreate(Activity.java:5231)
09-02 10:29:17.675: E/AndroidRuntime(1867): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
09-02 10:29:17.675: E/AndroidRuntime(1867): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2159)
09-02 10:29:17.675: E/AndroidRuntime(1867): ... 11 more
我已包含必要的权限,并且代码中没有错误。 但是它显示“不幸的是,UserMotion 已停止”。 请帮忙。
【问题讨论】:
你读过错误吗? 我对这个有点陌生。你能帮忙吗! @SagarNarang 是否是新的,如果你能阅读,你可以解决你的问题,因为错误告诉你该怎么做 @tyczi 说,他是新人,我们应该教他(@SagarNarang),他不知道在 logcat 中哪里可以找到他的错误。 @SagarNarang 这是显示您的 logcat 09-02 10:29:17.675: E/AndroidRuntime(1867): Caused by: java.lang.IllegalStateException: A required meta-data tag in your应用的 AndroidManifest.xml 不存在。 元素中必须有以下声明:此错误是由于标记清单中缺少此标记
<application>
....
....
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
</appliacation
【讨论】:
以上是关于用户运动检测应用程序不断崩溃的主要内容,如果未能解决你的问题,请参考以下文章