我正在创建一个框架,将测试android应用程序。在android应用程序中,他们实现了活动识别来了解用户的活动。我想在框架中测试功能。谁能告诉我如何在android实现模拟活动识别?
谢谢
我建议你子类化ActivityRecognitionClient并重新实现处理注册到更新的方法,并将其引用到调用子类ActivityRecognitionIntentService的未决意图。
你可以用一些人工数据周期性地调用你的服务。为了简单起见,我会使用带有handler的线程。
编辑:我已经添加了一个非常抽象的代码片段,应该给你的想法…
public class MainActivity extends FragmentActivity implements
ConnectionCallbacks, OnConnectionFailedListener {
private ActivityRecognitionClient mActivityRecognitionClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
mActivityRecognitionClient = MOCK ? new MockActivityRecognitionClient(getApplicationContext(), this, this) : new ActivityRecognitionClient(getApplicationContext(),
this, this);
}
...
/*
* Called by Location Services once the location client is connected.
*
* Continue by requesting activity updates.
*/
@Override
public void onConnected(Bundle dataBundle) {
/*
* Request activity recognition updates using the preset
* detection interval and PendingIntent. This call is
* synchronous.
*/
mActivityRecognitionClient.requestActivityUpdates(
DETECTION_INTERVAL_MILLISECONDS,
mActivityRecognitionPendingIntent);
/*
* Since the preceding call is synchronous, turn off the
* in progress flag and disconnect the client
*/
mInProgress = false;
mActivityRecognitionClient.disconnect();
}
...
}
/**
* Service that receives ActivityRecognition updates. It receives
* updates in the background, even if the main Activity is not visible.
*/
public class ActivityRecognitionIntentService extends IntentService {
...
/**
* Called when a new activity detection update is available.
*/
@Override
protected void onHandleIntent(Intent intent) {
...
}
...
}
public class MockActivityRecognitionClient extends ActivityRecognitionClient {
private List<ConnectionCallbacks> mConnectionCallbacksList;
private List<OnConnectionFailedListener> mConnectionFailedListenerlist;
private final Handler mHandler;
private long interval = 1000; //default 1000ms
private PendingIntent mPendingIntent;
private Context mContext;
public MockActivityRecognitionClient(Context context, ConnectionCallbacks connectedListener, OnConnectionFailedListener connectionFailedListener) {
super(context, connectedListener, connectionFailedListener);
registerConnectionCallbacks(connectedListener);
registerConnectionFailedListener(connectionFailedListener);
mHandler = new Handler(Looper.getMainLooper());
mContext = context;
}
@Override
public void requestActivityUpdates(long detectionIntervalMillis, PendingIntent callbackIntent) {
interval = detectionIntervalMillis;
mPendingIntent = callbackIntent;
mHandler.postDelayed(postLocationUpdateRunnable, interval);
}
@Override
public void removeActivityUpdates(PendingIntent callbackIntent) {
mHandler.removeCallbacks(postLocationUpdateRunnable);
}
@Override
public void connect() {
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
postConnected();
}
}, 2000);
}
private void postConnected() {
for(ConnectionCallbacks connectionCallbacks : mConnectionCallbacksList){
connectionCallbacks.onConnected(new Bundle()); //insert mocku bundle data
}
}
@Override
public boolean isConnected() {
}
@Override
public boolean isConnecting() {
}
@Override
public void registerConnectionCallbacks(ConnectionCallbacks listener) {
if(mConnectionCallbacksList == null){
mConnectionCallbacksList = new LinkedList<>();
}
mConnectionCallbacksList.add(listener);
}
@Override
public boolean isConnectionCallbacksRegistered(ConnectionCallbacks listener) {
return mConnectionCallbacksList.contains(listener);
}
@Override
public void unregisterConnectionCallbacks(ConnectionCallbacks listener) {
mConnectionCallbacksList.remove(listener);
}
@Override
public void registerConnectionFailedListener(OnConnectionFailedListener listener) {
...
}
@Override
public boolean isConnectionFailedListenerRegistered(OnConnectionFailedListener listener) {
...
}
@Override
public void unregisterConnectionFailedListener(OnConnectionFailedListener listener) {
...
}
@Override
public void disconnect() {
}
private final Runnable postLocationUpdateRunnable = new Runnable() {
@Override
public void run() {
try {
mPendingIntent.send(mContext, 1234, new Intent()); // in the intent should probably be the mocked activity data - I dont know the exact structure, it should be documented
} catch (PendingIntent.CanceledException e) {
e.printStackTrace();
}
mHandler.postDelayed(this, interval);
}
};
}
你可以检查这段代码,这也包括如何在特定活动发生时获取用户的位置。
MainActivity
class MainActivity : AppCompatActivity(), GoogleApiClient.OnConnectionFailedListener, GoogleApiClient.ConnectionCallbacks {
override fun onConnected(p0: Bundle?) {
requestActivityUpdates()
}
override fun onConnectionSuspended(p0: Int) {
Log.e("location", "connection suspended, retry to connect")
apiClient.connect()
}
override fun onConnectionFailed(p0: ConnectionResult) {
Log.e("location", "connection error ${p0.errorMessage}")
}
lateinit var apiClient: GoogleApiClient
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
init()
}
override fun onStart() {
super.onStart()
apiClient.connect()
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, arrayOf(android.Manifest.permission.ACCESS_COARSE_LOCATION), 100)
}
}
override fun onStop() {
super.onStop()
if (apiClient.isConnected)
apiClient.disconnect()
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
when (requestCode) {
100 -> {
if (grantResults.isNotEmpty() && grantResults[0] != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "You must assign permission of your location", Toast.LENGTH_SHORT).show()
finish()
}
}
}
}
private fun init() {
apiClient = GoogleApiClient.Builder(this).addApi(ActivityRecognition.API).addConnectionCallbacks(this).addOnConnectionFailedListener(this).build()
}
fun requestActivityUpdates() {
if (!apiClient.isConnected) {
Toast.makeText(this, "GoogleApiClient not yet connected", Toast.LENGTH_SHORT).show()
} else {
ActivityRecognition.getClient(this).requestActivityUpdates(0, getActivityDetectionPendingIntent())
}
}
fun removeActivityUpdates() {
ActivityRecognition.getClient(this).removeActivityUpdates(getActivityDetectionPendingIntent())
}
private fun getActivityDetectionPendingIntent(): PendingIntent {
val intent = Intent(this, ActivityRecognizeService::class.java)
return PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
}
}
class ActivityRecognizeService : IntentService("LjRecognize") {
lateinit var location: Location
private var fusedLocationClient: FusedLocationProviderClient? = null
override fun onHandleIntent(intent: Intent?) {
if (intent == null)
return
if (ActivityRecognitionResult.hasResult(intent)) {
val result = ActivityRecognitionResult.extractResult(intent)
val time = System.currentTimeMillis()
result.probableActivities.forEach {
when (it.type) {
DetectedActivity.IN_VEHICLE -> {
Log.e("Activity found", "on vehicle at " + time + " with confidence of " + it.confidence)
}
DetectedActivity.ON_BICYCLE -> {
Log.e("Activity found", "on bicycle at " + time + " with confidence of " + it.confidence)
}
DetectedActivity.ON_FOOT -> {
Log.e("Activity found", "on foot at " + time + " with confidence of " + it.confidence)
getLocation()
}
DetectedActivity.STILL -> {
Log.e("Activity found", "still at " + time + " with confidence of " + it.confidence)
}
DetectedActivity.UNKNOWN -> {
Log.e("Activity found", "unknown at " + time + " with confidence of " + it.confidence)
}
DetectedActivity.TILTING -> {
Log.e("Activity found", "tilted at " + time + " with confidence of " + it.confidence)
}
}
}
}
}
private fun getLocation() {
if (fusedLocationClient == null)
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
fusedLocationClient!!.lastLocation.addOnSuccessListener {
if (it != null)
location = it
Log.e("location", "found -> lat: ${location.latitude}, lng: ${it.longitude}")
}
} else {
startActivity(Intent(this, MainActivity::class.java))
}
}
}
别忘了添加权限
<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />