接近警报发射两次?

时间:2012-05-02 11:19:36

标签: java android eclipse osmdroid

接收器:

public class ProximityAlert extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        int id = intent.getIntExtra("id", -1);
        String title = intent.getStringExtra("Title");

        Intent showDialog = new Intent(context, ShowMapDialog.class);
        showDialog.putExtra("id", id);
        showDialog.putExtra("Title", title);
        context.startActivity(showDialog);
    }

}

ShowMapDialog.java:

public class ShowMapDialog extends Activity {

PowerManager.WakeLock wakeLock;
AlertDialog alertbox;

@Override
public void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);

    Bundle extras = getIntent().getExtras();

    Prefs sp = new Prefs();

    int lastplaceid = sp.getLastPlaceID(getApplicationContext());
    boolean nopopup = sp.getNoPopup(getApplicationContext());

    final int id = extras.getInt("id");
    String Title = extras.getString("Title");

    Log.d("id+title",id+"+"+Title);

    PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
    wakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "Place of Interest");

    if(id != lastplaceid && !nopopup) {
        wakeLock.acquire();

        sp.setLastPlaceID(getApplicationContext(), id);

        Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
        int dot = 200;
        int dash = 500;
        int long_gap = 1000;
        long[] pattern = {0, dash, dot, dash, long_gap};
        v.vibrate(pattern, -1);

        alertbox = new AlertDialog.Builder(ShowMapDialog.this).create();
        alertbox.setTitle(getString(R.string.dialogTitle));
        alertbox.setMessage(getString(R.string.dialogShowPlaceText1)+Title+getString(R.string.dialogShowPlaceText2));
        alertbox.setButton(getString(R.string.dialogShowPlaceYes), new DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which) {
                Intent showPlace = new Intent(getApplicationContext(),Showplace.class);
                showPlace.putExtra("id", id);
                startActivity(showPlace);
            }
        });
        alertbox.setButton2(getString(R.string.dialogShowPlaceNo), new DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int which) {
                finish();
            }
        });
        alertbox.show();
    } else if(id != lastplaceid && nopopup){
        wakeLock.acquire();
        sp.setLastPlaceID(getApplicationContext(), id);
        Intent showPlace = new Intent(getApplicationContext(),Showplace.class);
        showPlace.putExtra("id", id);
        startActivity(showPlace);
    } else {
        finish();
    }
}

@Override
public void onPause(){
    super.onPause();
    wakeLock.release();
    alertbox.dismiss();
    finish();
}

}

创建ProximityAlerts:

    private void setProximityAlert(String Title, double lat, double lon, float radius, final int id, int requestCode){
        // Expiration is x Minutes (x mins * 60secs * 1000milliSecs)
        long expiration = -1;

        Intent intent = new Intent(PROXIMITY_INTENT_ACTION);
        intent.putExtra("id", id);
        intent.putExtra("Title", Title);

        PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), requestCode, intent, PendingIntent.FLAG_CANCEL_CURRENT);

        mlocManager.addProximityAlert(lat, lon, radius, expiration, pendingIntent);
    }

    public void placeMarkersPoints(){
        this.dh = new DataHelper(ShowMap.this);
        List<Pontos> list = this.dh.selectAll();
        markerPlaces = new OverlayPlaces(getResources().getDrawable(R.drawable.marker_places), mapView);
        for(Pontos p : list){
             markerPlaces.addPoint(new GeoPoint(p.getLat(),p.getLng()),p.getName().toString(),Integer.toString(p.getId()));
             setProximityAlert(p.getName().toString(), p.getLat(), p.getLng(), p.getRadius(), p.getId(), p.getId());
        }
        mapView.getOverlays().add(markerPlaces);
        mapView.invalidate();
    }

我在onCreate上注册了接收器,如下所示:

    br = new ProximityAlert();
    mIntentFilter = new IntentFilter(PROXIMITY_INTENT_ACTION);

的onPause:

@Override
public void onPause() {
    super.onPause();
    mlocManager.removeUpdates(this);
    unregisterReceiver(br);
}

的onResume:

@Override
protected void onResume() {
    super.onResume();
    mlocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 10, this);
    registerReceiver(br, mIntentFilter);
}

当我浏览第二个ProximityAlert时,它会执行两次代码:Log.d("id+title",id+"+"+Title);

有什么想法吗?如果需要,我可以发布更多代码:)

2 个答案:

答案 0 :(得分:1)

实际上我的问题出在BroadcastReceivers上。

我正在摧毁他们,但不是很正确,所以有时候他们会加倍,或者加倍,或者加入。

谢谢,但我自己解决了这个问题:)

答案 1 :(得分:1)

每次申请恢复时,您都在注册接收器。

public enum DatabaseState
{
    Empty = 0,
    Learning = 1,
    Updating = 2,
    Stable = 3,
    Exiting = 4
};

public class NetworkDB
{
    public Dictionary<string, NetworkDevice> database;
    private Queue<Action<NetworkDevice>> jobs;
    private string _community;
    private string _ipaddress;

    private Object _statelock = new Object();
    private DatabaseState _state = DatabaseState.Empty;

    private readonly int workers = 4;
    private Object _threadswaitinglock = new Object();
    private int _threadswaiting = 0;

    public Dictionary<string, NetworkDevice> Database { get => database; set => database = value; }

    public NetworkDB(string community, string ipaddress)
    {
        _community = community;
        _ipaddress = ipaddress;
        database = new Dictionary<string, NetworkDevice>();
        jobs = new Queue<Action<NetworkDevice>>();
    }

    public void Start()
    {
        NetworkDevice nd = SNMP.GetDeviceInfo(new IpAddress(_ipaddress), _community);
        if (nd.Status > NetworkDeviceStatus.Unknown)
        {
            database.Add(nd.Id, nd);
            _state = DatabaseState.Learning;
            nd.Update(this); // The first job is done by the main thread 

            for (int i = 0; i < workers; i++)
            {
                Thread t = new Thread(JobRemove);
                t.Start();
            }

            lock (_statelock)
            {
                if (_state == DatabaseState.Learning)
                {
                    Monitor.Wait(_statelock);
                }
            }

            lock (_statelock)
            {
                if (_state == DatabaseState.Updating)
                {
                    Monitor.Wait(_statelock);
                }
            }

            foreach (KeyValuePair<string, NetworkDevice> n in database)
            {
                using (System.IO.StreamWriter file = new System.IO.StreamWriter(n.Value.Name + ".txt")
                {
                    file.WriteLine(n);

                }
            }
        }
    }

    public void JobInsert(Action<NetworkDevice> func, NetworkDevice nd)
    {
        lock (jobs)
        {
            jobs.Enqueue(item);
            if (jobs.Count == 1)
            {
                // wake up any blocked dequeue
                Monitor.Pulse(jobs);
            }
        }
    }

    public void JobRemove()
    {
        Action<NetworkDevice> item;
        lock (jobs)
        {
            while (jobs.Count == 0)
            {
                lock (_threadswaitinglock)
                {
                    _threadswaiting += 1;
                    if (_threadswaiting == workers)
                        Monitor.Pulse(_statelock);
                }
                Monitor.Wait(jobs);
            }

            lock (_threadswaitinglock)
            {
                _threadswaiting -= 1;
            }

            item = jobs.Dequeue();
            item.Invoke();
        }
    }

    public bool NetworkDeviceExists(NetworkDevice nd)
    {
        try
        {
            Monitor.Enter(database);
            if (database.ContainsKey(nd.Id))
            {
                return true;
            }
            else
            {
                database.Add(nd.Id, nd);
                Action<NetworkDevice> action = new Action<NetworkDevice>(UpdateDeviceInfo);
                jobs.Enqueue(action);
                return false;
            }
        }
        finally
        {

            Monitor.Exit(database);
        }
    }

    //Job1 - Learning -> Update device info
    public void UpdateDeviceInfo(NetworkDevice nd)
    {
        nd.Update(this);
        try
        {
            Monitor.Enter(database);
            nd.Status = NetworkDeviceStatus.Self;
        }
        finally
        {
            Monitor.Exit(database);
        }
    }

    //Job2 - Updating -> After Learning, create links between neighbours
    private void UpdateLinks()
    {

    }
}

因此,每次触发每个接近警报(@Override protected void onResume() { super.onResume(); ... registerReceiver(br, mIntentFilter); } )时,将触发多个接收器实例(每次恢复活动时一个)。想象一下,你有一个来电者和一群克隆的接收者,所有人都同时回答。

创建PendingIntent很好,只要每次暂停应用程序{@ 1}}时删除/销毁邻近警报。

否则,在主/导航活动中创建一次。在这种情况下,即使应用程序处于后台(可能[报警应用]或可能不[显示更改,例如]是所需行为),接收器仍将继续触发。

相关问题