web-dev-qa-db-ja.com

サービスからアクティビティの参照を取得する

サービスからメインアクティビティへの参照を取得する必要があります。

これは私のデザインです:

MainActivity.Java

public class MainActivity extends Activity{
private Intent myIntent;
onCreate(){
 myIntent=new Intent(MainActivity.this, MyService.class);

 btnStart.setOnClickListener(new OnClickListener(){
  public void onClick(View V){
   startService(myIntent);
   });
}}

MyService.Java

class MyService extends Service{

 public IBinder onBind(Intent intent) {
  return null;
 }

 onCreate(){
 //Here I need to have a MainActivity reference
 //to pass it to another object
 }
}

これどうやってするの?

[編集]

答えてくれてありがとう!このアプリはWebサーバーであり、現時点ではスレッドでのみ機能します。代わりにサービスを使用して、バックグラウンドでも機能させるようにします。問題は、アセットからページを取得するクラスがあることです。この操作を行うには、次のメソッドを使用する必要があります。

InputStream iS =myActivity.getAssets().open("www/"+filename); 

現在、私のプロジェクトにはアクティビティが1つしかなく、サービスがないため、メインアクティビティの参照をそれ自体から直接渡すことができます。

WebServer ws= new DroidWebServer(8080,this);

では、このアプリをサービスで動作させるには、デザインを何に変更する必要がありますか?

9
supergiox

なぜこれが必要なのか説明していません。しかし、これは間違いなく悪いデザインです。アクティビティへの参照を保存することは、アクティビティで最初に行うことですすべきではありません。できますが、アクティビティのライフサイクルを追跡し、onDestroy()が呼び出された後に参照を解放する必要があります。これを行わないと、メモリリークが発生します(たとえば、構成が変更された場合)。そして、まあ、onDestroy()が呼び出された後、Activityは死んでいると見なされ、とにかく役に立たない可能性があります。

したがって、参照をServiceに保存しないでください。代わりに、達成する必要があることを説明してください。私はそこにもっと良い選択肢があると確信しています。


[〜#〜] update [〜#〜]

わかりました。実際にアクティビティを参照する必要はありません。代わりに、Contextへの参照が必要です(この場合、Activityまたはその他のコンポーネントへの参照を保持しないためにApplicationContextである必要があります)。

WebServiceリクエストを処理する別のクラスがあると仮定します。

class WebService 
{   
     private final Context mContext;
     public WebService(Context ctx) 
     {
        //The only context that is safe to keep without tracking its lifetime
        //is application context. Activity context and Service context can expire
        //and we do not want to keep reference to them and prevent 
        //GC from recycling the memory.
        mContext = ctx.getApplicationContext(); 
     }

     public void someFunc(String filename) throws IOException 
     {
         InputStream iS = mContext.getAssets().open("www/"+filename); 
     }
}

これで、Service(このようなバックグラウンドタスクに推奨)から、またはActivity(Webサービス呼び出しや長いバックグラウンドタスクが関与)。

Serviceの例:

class MyService extends Service
{
    WebService mWs;
    @Override
    public void onCreate()
    {
        super.onCreate();
        mWs = new WebService(this);

       //you now can call mWs.someFunc() in separate thread to load data from assets.
    }

    @Override
    public IBinder onBind(Intent intent)
    {
        return null;
    }
}
9
inazaruk

サービスとアクティビティの間で通信するには、AIDLを使用する必要があります。このリンクの詳細:

編集:(ありがとうRenanMalke Stigliani) http://developer.Android.com/guide/components/aidl.html

2
IncrediApp

アクティビティとサービスが別々のapkにない限り、AIDLはやり過ぎです。

ローカルサービスへのバインダーを使用するだけです。 (ここでの完全な例: http://developer.Android.com/reference/Android/app/Service.html

public class LocalBinder extends Binder {
        LocalService getService() {
            return LocalService.this;
        }
    }
2
Ajit Aranha

Inazarukのコメントに同意します。ただし、アクティビティとサービス間の通信に関しては、AIDL(上記のとおり)、Messenger、BroadcastReiceverなどのいくつかの選択肢があります。MessengerメソッドはAIDLに似ていますが、インターフェイスを定義する必要はありません。ここから始めることができます:

http://developer.Android.com/resources/samples/ApiDemos/src/com/example/Android/apis/app/MessengerService.html

0
SBerg413