我已经实现了一个使用c2dm 框架接收推送消息的应用程序。它会在新消息成功到达时显示通知。
但是,如何添加此功能?
当接收者有新消息时,如果它正在运行,请通知我的 Activity。
我尝试使用侦听器模式,即。将活动的引用提供给接收者,但它返回 viewroot callfromwrongthreadexception。
这个怎么解决,thx
我已经实现了一个使用c2dm 框架接收推送消息的应用程序。它会在新消息成功到达时显示通知。
但是,如何添加此功能?
当接收者有新消息时,如果它正在运行,请通知我的 Activity。
我尝试使用侦听器模式,即。将活动的引用提供给接收者,但它返回 viewroot callfromwrongthreadexception。
这个怎么解决,thx
使用监听器。这是接收器的示例,它在接收到新位置时通知 Activity。自定义它:
import android.location.Location;
public interface OnNewLocationListener {
public abstract void onNewLocationReceived(Location location);
}
接收者:
import java.util.ArrayList;
import org.mabna.order.utils.Farsi;
import org.mabna.order.utils.MessageBox;
import org.mabna.order.utils.Utilities;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.location.GpsStatus;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.view.Gravity;
import android.widget.Toast;
public class ReceiverPositioningAlarm extends BroadcastReceiver {
public static final String COMMAND = "SENDER";
public static final int SENDER_ACT_DOCUMENT = 0;
public static final int SENDER_SRV_POSITIONING = 1;
public static final int MIN_TIME_REQUEST = 5 * 1000;
public static final int MIN_DISTANCE = 10;// in meters
public static final String ACTION_REFRESH_SCHEDULE_ALARM =
"org.mabna.order.ACTION_REFRESH_SCHEDULE_ALARM";
private static Location currentLocation;
private static Location prevLocation;
private static Context _context;
private String provider = LocationManager.GPS_PROVIDER;
private static Intent _intent;
private static LocationManager locationManager;
private static LocationListener locationListener = new LocationListener() {
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
try {
String strStatus = "";
switch (status) {
case GpsStatus.GPS_EVENT_FIRST_FIX:
strStatus = "GPS_EVENT_FIRST_FIX";
break;
case GpsStatus.GPS_EVENT_SATELLITE_STATUS:
strStatus = "GPS_EVENT_SATELLITE_STATUS";
break;
case GpsStatus.GPS_EVENT_STARTED:
strStatus = "GPS_EVENT_STARTED";
break;
case GpsStatus.GPS_EVENT_STOPPED:
strStatus = "GPS_EVENT_STOPPED";
break;
default:
strStatus = String.valueOf(status);
break;
}
Toast.makeText(_context,
"Status: " + strStatus,
Toast.LENGTH_SHORT).show();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
@Override
public void onLocationChanged(Location location) {
try {
Toast.makeText(_context,
"***new location***",
Toast.LENGTH_SHORT).show();
gotLocation(location);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
@Override
public void onReceive(final Context context, Intent intent) {
Toast.makeText(context, "new request received by receiver",
Toast.LENGTH_SHORT).show();
_context = context;
_intent = intent;
locationManager = (LocationManager) context
.getSystemService(Context.LOCATION_SERVICE);
if (locationManager.isProviderEnabled(provider)) {
locationManager.requestLocationUpdates(provider, MIN_TIME_REQUEST,
MIN_DISTANCE, locationListener);
Location gotLoc = locationManager.getLastKnownLocation(provider);
gotLocation(gotLoc);
} else {
t.setGravity(Gravity.CENTER, 0, 0);
t.show();
Intent settinsIntent = new Intent(
android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
settinsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
_context.startActivity(settinsIntent);
}
}
private static void gotLocation(Location location) {
prevLocation = currentLocation == null ?
null : new Location(currentLocation);
currentLocation = location;
if (isLocationNew()) {
// saveLocation(location);
// informing the classes outside of this class that e new point
// received
OnNewLocationReceived(location);
Toast.makeText(_context, "new location saved", Toast.LENGTH_SHORT)
.show();
stopLocationListener();
}
}
private static boolean isLocationNew() {
if (currentLocation == null) {
return false;
} else if (prevLocation == null) {
return true;
} else if (currentLocation.getTime() == prevLocation.getTime()) {
return false;
} else {
return true;
}
}
public static void stopLocationListener() {
locationManager.removeUpdates(locationListener);
Toast.makeText(_context, "provider stoped", Toast.LENGTH_SHORT)
.show();
}
// listener ----------------------------------------------------
static ArrayList<OnNewLocationListener> arrOnNewLocationListener =
new ArrayList<OnNewLocationListener>();
// Allows the user to set a OnNewLocationListener outside of this class and
// react to the event.
// A sample is provided in ActDocument.java in method: startStopTryGetPoint
public static void setOnNewLocationListener(
OnNewLocationListener listener) {
arrOnNewLocationListener.add(listener);
}
public static void clearOnNewLocationListener(
OnNewLocationListener listener) {
arrOnNewLocationListener.remove(listener);
}
// This function is called after the new point received
private static void OnNewLocationReceived(Location location) {
// Check if the Listener was set, otherwise we'll get an Exception when
// we try to call it
if (arrOnNewLocationListener != null) {
// Only trigger the event, when we have any listener
for (int i = arrOnNewLocationListener.size() - 1; i >= 0; i--) {
arrOnNewLocationListener.get(i).onNewLocationReceived(
location);
}
}
}
}
活动中:
Intent intentToFire = new Intent(
ReceiverPositioningAlarm.ACTION_REFRESH_SCHEDULE_ALARM);
intentToFire.putExtra(ReceiverPositioningAlarm.COMMAND,
ReceiverPositioningAlarm.SENDER_ACT_DOCUMENT);
sendBroadcast(intentToFire);
OnNewLocationListener onNewLocationListener = new OnNewLocationListener() {
@Override
public void onNewLocationReceived(Location location) {
try {
// do everything you want
ReceiverPositioningAlarm.clearOnNewLocationListener(this);
} catch (Exception e) {
MessageBox.showException(ActDocument.this, e);
}
}
};
// start listening for new location
ReceiverPositioningAlarm.setOnNewLocationListener(
onNewLocationListener);
我正在寻找类似的操作:根据 BroadcastReceiver(准确地说是 C2DM 注册)更新活动的 UI TextView。我callFromWrongThreadException
试图在自定义线程中更新 ui。
我的解决方案很简单。为清楚起见,我将使用 breceivernail 的答案。我修改了OnNewLocationReceived
Activity 中的方法runOnUiThread()
。
@Override
public void OnNewLocationReceived(Location location) {
runOnUiThread(new Runnable() {
public void run(){
/* update UI here */
}
});
};
如果你得到callFromWrongThreadException
breceivernail 的答案是正确的,你必须弄清楚你在堆栈跟踪的错误位置调用了什么。如果您在更新 UI 时遇到问题,我上面的解决方案可以解决异常。