2

以下のサンプルプロジェクトに基づいています。(ここから撮影)

文字列がコンストラクタに渡されたときに起動するのに、 andが渡されBroadcastReceiverたときに起動しないのはなぜですか?actionIntentContextSomeOtherActivity.class

           // this works
           Intent intent = new Intent(PROX_ALERT_INTENT);        

           //this does not
           Intent intent = new Intent(this, ProximityIntentReceiver.class);  
           intent.setAction(PROX_ALERT_INTENT);                             

ProximityAlertActivity.java:

package com.androidmyway.demo.proxymityalert;

import android.app.Activity;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.location.LocationManager;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;


public class ProximityAlertActivity extends Activity {
    private static final long POINT_RADIUS = 100; // in Meters
    private static final long PROX_ALERT_EXPIRATION = -1; // It will never expire
    private static final String PROX_ALERT_INTENT = "com.androidmyway.demo.ProximityAlert";
    private LocationManager locationManager;
    private EditText latitudeEditText;
    private EditText longitudeEditText;
    private Button addAlertButton;

    @Override
    public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_proxymity);

            locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

            latitudeEditText = (EditText) findViewById(R.id.point_latitude);
            longitudeEditText = (EditText) findViewById(R.id.point_longitude);
            addAlertButton = (Button) findViewById(R.id.add_alert_button);

            addAlertButton.setOnClickListener(new OnClickListener() {
                  public void onClick(View v) {
                         addProximityAlert();
                  }
            });

    }

    private void addProximityAlert() {
           double latitude = Double.parseDouble(latitudeEditText.getText().toString());
           double longitude = Double.parseDouble(longitudeEditText.getText().toString());
           //Intent intent = new Intent(PROX_ALERT_INTENT);           
           Intent intent = new Intent(this, ProximityIntentReceiver.class); 
           intent.setAction(PROX_ALERT_INTENT);
           PendingIntent proximityIntent = PendingIntent.getBroadcast(this, 2, intent,         PendingIntent.FLAG_UPDATE_CURRENT);
           locationManager.addProximityAlert(
                  latitude, // the latitude of the central point of the alert region
                  longitude, // the longitude of the central point of the alert region
                  POINT_RADIUS, // the radius of the central point of the alert region, in meters
                  PROX_ALERT_EXPIRATION, // time for this proximity alert, in milliseconds, or -1 to     indicate no                           expiration
                  proximityIntent // will be used to generate an Intent to fire when entry to or exit from the alert region is detected
           );

           IntentFilter filter = new IntentFilter(PROX_ALERT_INTENT);
           registerReceiver(new ProximityIntentReceiver(), filter);
           Toast.makeText(getApplicationContext(),"Alert Added",Toast.LENGTH_SHORT).show();
    }    
}

ProximityIntentReceiver:

package com.androidmyway.demo.proxymityalert;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.location.LocationManager;
import android.util.Log;

public class ProximityIntentReceiver extends BroadcastReceiver {
    private static final int NOTIFICATION_ID = 1000;

    @SuppressWarnings("deprecation")
    @Override
    public void onReceive(Context context, Intent intent) {
        String key = LocationManager.KEY_PROXIMITY_ENTERING;
        Boolean entering = intent.getBooleanExtra(key, false);
        if (entering) {
            Log.d(getClass().getSimpleName(), "entering");
        }else {
            Log.d(getClass().getSimpleName(), "exiting");
        }
        NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);

        Intent notificationIntent = new Intent(context, ProximityAlertActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
        Notification notification = createNotification();
        notification.setLatestEventInfo(context, "Proximity Alert!", "You are near your point of interest.", pendingIntent);

        notificationManager.notify(NOTIFICATION_ID, notification);
    }

    private Notification createNotification() {
        Notification notification = new Notification();
        notification.icon = R.drawable.ic_launcher;
        notification.when = System.currentTimeMillis();
        notification.flags |= Notification.FLAG_AUTO_CANCEL;
        notification.flags |= Notification.FLAG_SHOW_LIGHTS;
        notification.defaults |= Notification.DEFAULT_VIBRATE;
        notification.defaults |= Notification.DEFAULT_LIGHTS;
        notification.ledARGB = Color.WHITE;
        notification.ledOnMS = 1500;
        notification.ledOffMS = 1500;
        return notification;
    }
}

AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.androidmyway.demo.proxymityalert"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="15" />

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.INTERNET"></uses-permission>


    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@android:style/Theme.Black.NoTitleBar" >
        <activity
            android:name=".ProximityAlertActivity"
        >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
4

2 に答える 2

4

私は2つの質問をしていることがわかりました:

Q1 :文字列がコンストラクタに渡されたときに起動するのに、およびが渡されBroadcastReceiverたときに起動しないのはなぜですか? (これは一般的な質問であり、投稿したコードに固有のものではないと思います)ActionIntentContextSomeOtherActivity.class

Q2 :文字列がコンストラクターに渡されると起動するのに、とが渡されるとBroadcastReceiver起動しないのはなぜですか? (これは、プログラムで登録されたレシーバーを使用するため、投稿したコードに固有のものです)ActionIntentContextNameOfReceiver.class

       //this works
       Intent intent = new Intent(PROX_ALERT_INTENT);        

       //this does not
       Intent intent = new Intent(this, ProximityIntentReceiver.class);  
       intent.setAction(PROX_ALERT_INTENT); 

いくつかの調査の後、私は正しい答えを持っていると信じています:

ANS1 :コンストラクターを呼び出した後にAction手動で を追加しても、BroadcastReceiver はトリガーされません。IntentsのAndroid 開発者ページに説明があります。Intentnew Intent(context, SomeOtherActivity.class)

" Android delivers an explicit intent to an instance of the designated target class. Nothing in the Intent object other than the component name matters for determining which component should get the intent."

したがって、手動で を追加しActionても効果はありません。さらに、明示的に使用すると、コンストラクターIntentで設定できる唯一のクラスは、明示的に呼び出したいクラスです。この場合、他のクラスを渡すことは意味がありません。IntentBroadcastReceiver

これにより、ANS2に移動します。

CommonsWare は、次の SO の質問に対して非常に明確な回答を提供しています。

アラートを登録しているのに近接アラートを受信しないのはなぜですか?

問題は、受信者をプログラムで登録していることです。これにより、IntentFilter. 上で述べたように、一度明示的に使用するIntent と、重要なのはコンポーネント名だけです。レシーバーを動的に登録するときに、コンポーネント名 (レシーバー名) ではなく でAction定義されたをリッスンしていると思います。IntentFilter

明示的な使用Intent:

Intent intent = new Intent(this, ProximityIntentReceiver.class); 

マニフェストに静的に登録されたレシーバーとともに:

<receiver android:name="ProximityIntentReceiver" />

問題を修正しました。

私が何か間違っている場合は、私を修正してください。

于 2013-09-27T00:14:06.437 に答える
0

私が間違っている場合は訂正してください。構造は次のとおりです。

Intent intent = new Intent(this, SomeActivity.class); 

ブロードキャスト用ではなく、別のアクティビティ、インテント サービスなどを開始するように設計されています。

これは、他のアプリケーションがブロードキャストを取得できるという理由からも理にかなっています。ブロードキャストにクラス参照が含まれていた場合、他のアプリケーションはそのコードを呼び出すことができません。

上記のインテント構築の Javadoc:

特定のコンポーネントのインテントを作成します。他のすべてのフィールド (アクション、データ、タイプ、クラス) は null ですが、後で明示的な呼び出しで変更できます。これにより、システムに依存して適切なクラスを見つけるのではなく、ハードコーディングされたクラス名を実行することを目的としたインテントを作成する便利な方法が提供されます。この影響の詳細については、setComponent(ComponentName) を参照してください。

後でアクションを設定しているように見えますが、Android のフードの下では、そのインテントはとにかく特定のコンポーネントに対するものと見なされていると思います。

于 2013-09-23T21:14:27.357 に答える