如何从服务获取数据到活动

Posted

技术标签:

【中文标题】如何从服务获取数据到活动【英文标题】:How to get data from service to activity 【发布时间】:2013-08-10 02:52:17 【问题描述】:

在我的应用中,我有一个活动和一个服务...... 该服务将广播从 GPS 数据收集的消息... Activity 应该接收广播消息并更新 UI...

我的代码

public class LocationPollerDemo extends Activity 
    private static final int PERIOD = 10000; // 30 minutes
    private PendingIntent pi = null;
    private AlarmManager mgr = null;
    private double lati;
    private double longi;
    private ServiceReceiver serviceReceiver;

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

        mgr = (AlarmManager) getSystemService(ALARM_SERVICE);

        Intent i = new Intent(this, LocationPoller.class);

        i.putExtra(LocationPoller.EXTRA_INTENT, new Intent(this, ServiceReceiver.class));
        i.putExtra(LocationPoller.EXTRA_PROVIDER, LocationManager.GPS_PROVIDER);

        pi = PendingIntent.getBroadcast(this, 0, i, 0);
        mgr.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime(), PERIOD, pi);

        DebugLog.logTrace("On Create Demo");
        Toast.makeText(this, "Location polling every 30 minutes begun", Toast.LENGTH_LONG).show();
        serviceReceiver = new ServiceReceiver();
        IntentFilter filter = new IntentFilter("me");
        this.registerReceiver(serviceReceiver, filter);
    

    class ServiceReceiver extends BroadcastReceiver 
        @Override
        public void onReceive(Context context, Intent intent) 
            File log = new File(Environment.getExternalStorageDirectory(), "Location2.txt");
            DebugLog.logTrace(Environment.getExternalStorageDirectory().getAbsolutePath());

            try 
                BufferedWriter out = new BufferedWriter(new FileWriter(log.getAbsolutePath(), log.exists()));

                out.write(new Date().toString());
                out.write(" : ");

                Bundle b = intent.getExtras();
                Location loc = (Location) b.get(LocationPoller.EXTRA_LOCATION);
                String msg;

                if (loc == null) 
                    loc = (Location) b.get(LocationPoller.EXTRA_LASTKNOWN);

                    if (loc == null) 
                        msg = intent.getStringExtra(LocationPoller.EXTRA_ERROR);
                     else 
                        msg = "TIMEOUT, lastKnown=" + loc.toString();
                    
                 else 
                    msg = loc.toString();
                

                if (msg == null) 
                    msg = "Invalid broadcast received!";
                

                out.write(msg);
                out.write("\n");
                out.close();
             catch (IOException e) 
                Log.e(getClass().getName(), "Exception appending to log file", e);
                DebugLog.logException(e);
            
        
    

当我使用此代码时,它无法正常工作... 我在单独的文件中使用 ServiceReceiver 类工作正常.... 请告诉我...!!

【问题讨论】:

【参考方案1】:

在我的服务类中我写了这个

private static void sendMessageToActivity(Location l, String msg) 
    Intent intent = new Intent("GPSLocationUpdates");
    // You can also include some extra data.
    intent.putExtra("Status", msg);
    Bundle b = new Bundle();
    b.putParcelable("Location", l);
    intent.putExtra("Location", b);
    LocalBroadcastManager.getInstance(context).sendBroadcast(intent);

而在 Activity 端,我们必须接收此广播消息

LocalBroadcastManager.getInstance(getActivity()).registerReceiver(
            mMessageReceiver, new IntentFilter("GPSLocationUpdates"));

通过这种方式,您可以向 Activity 发送消息。 这里 mMessageReceiver 是该类中的类,您将执行任何您想要的操作....

在我的代码中我这样做了......

private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() 
    @Override
    public void onReceive(Context context, Intent intent) 
        // Get extra data included in the Intent
        String message = intent.getStringExtra("Status");
        Bundle b = intent.getBundleExtra("Location");
        lastKnownLoc = (Location) b.getParcelable("Location");
        if (lastKnownLoc != null) 
            tvLatitude.setText(String.valueOf(lastKnownLoc.getLatitude()));
            tvLongitude
                    .setText(String.valueOf(lastKnownLoc.getLongitude()));
            tvAccuracy.setText(String.valueOf(lastKnownLoc.getAccuracy()));
            tvTimestamp.setText((new Date(lastKnownLoc.getTime())
                    .toString()));
            tvProvider.setText(lastKnownLoc.getProvider());
        
        tvStatus.setText(message);
        // Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
    
;

【讨论】:

永远不要忘记在 onPause 中取消注册接收者 @FaisalNaseer 如何注销你能提供一些示例代码吗 只需unregisterReceiver(mMessageReceiver ); 在“onDestroy”方法上注销接收器:) LocalBroadcastManager.getInstance(context).sendBroadcast(intent);这是活动上下文还是服务上下文?【参考方案2】:

使用 Handler 是一个好方法。 在您的 Activity 中创建一个扩展 Handler 的 innerClass 并覆盖 handleMessage 方法。

然后,在您的 ServiceReceiver 类中,创建一个处理程序变量和一个构造函数,例如:

public ServiceReceiver(Handler handler)
   this.handler = handler;

因此,在您的活动中,创建您的自定义处理程序并将其传递给您的服务。因此,当您想将一些数据放入您的活动时,您可以将handler.sendMessage() 放入您的服务中(它将调用您的内部类的handleMessage)。

【讨论】:

【参考方案3】:

如何从 IntentService 向 Activity 发送数据?

如果服务仅用于一种方式,则无需绑定服务 沟通。对于这种情况,使用 IntentService + BroadcastReceiver 很容易。

示例:

你有一个 BackgroundService 计算信号强度并将数据发送回活动每个 第二。 Activity 在 GraphView 中显示数据。

怎么做?

从服务发送数据

public class TrackWifiService extends IntentService 

    public TrackWifiService() 
        super("wifiService");
    

    protected void onHandleIntent(@Nullable Intent intent) 

        sendDataToActivity()
    

   private void sendDataToActivity()
   
        Intent sendLevel = new Intent();
        sendLevel.setAction("GET_SIGNAL_STRENGTH");
        sendLevel.putExtra( "LEVEL_DATA","Strength_Value");
        sendBroadcast(sendLevel);

   



从服务接收数据 为此,您的 Activity 应注册 BroadcastReceiver

public class TrackWifiActivity extends AppCompatActivity 

   WifiLevelReceiver receiver;

   @Override
   public void onCreate(Bundle savedInstanceState)
   
      super.onCreate(savedInstanceState);
      setContentView(R.layout.track_wifi_activity_layout);
      receiver = new WifiLevelReceiver();
      registerReceiver(receiver, new IntentFilter("GET_SIGNAL_STRENGTH"));  //<----Register
   


   @Override
   public void onStop()
   
       super.onStop();
       unregisterReceiver(receiver);           //<-- Unregister to avoid memoryleak
   

   class WifiLevelReceiver extends BroadcastReceiver 

       @Override
       public void onReceive(Context context, Intent intent) 

           if(intent.getAction().equals("GET_SIGNAL_STRENGTH"))
           
              int level = intent.getIntExtra("LEVEL_DATA",0);

              // Show it in GraphView
           
       

   


注意:

如果您想使用LocalBroadcastReceiver 而不是广播接收器。你可以看看How to convert BroadCastReceiver to LocalBroadcastReceiver

相关链接

See Full projectWhat is an IntentService?Difference between Bound and Unbound Services

【讨论】:

如果用户最小化应用程序,它将取消注册接收器。所以最好在onStart()注册。 取决于用例是否需要数据,即使您的应用程序在后台,然后在 onCreate() 中的 bindService() 和 onDestroy() 中的 unbindService() 中注册和取消注册 阅读更多 ***.com/questions/8614335/…在官方文档中阅读更多信息developer.android.com/guide/components/…【参考方案4】:

services交流的三种明显方式

    使用 Intent。 使用 AIDL。 使用服务对象本身(作为单例)。

【讨论】:

【参考方案5】:
class MainActivity : AppCompatActivity() 
    private val sb = object :SerToBroad()
        override fun broadcastResult(connected: String?) 
           t(connected)
        

    
    override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    
  fun t(connected: String?)
  
    Toast.makeText(MainActivity@this, connected, Toast.LENGTH_SHORT).show()

    override fun onStart() 
        super.onStart()
        startService(Intent(MainActivity@ this, MService::class.java))
        val inf = IntentFilter()
        inf.addAction(MService.ACTION)
        registerReceiver(sb, inf)
    

    override fun onStop() 
        super.onStop()
        unregisterReceiver(sb)
    

-------------------------------------
//Service class 

    class MService : Service() 
   companion object const val   ACTION = "MY_ACTION"
    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int 
        val intent = Intent()
        intent.action = ACTION

        intent.putExtra("DATA", "10")

        sendBroadcast(intent)
        return super.onStartCommand(intent, flags, startId)
    
--------------------------------------------------
broadcast

abstract class SerToBroad : BroadcastReceiver() 
    override fun onReceive(p0: Context?, p1: Intent?) 
        val rec = p1?.getStringExtra("DATA")
        broadcastResult(rec)


    

    abstract fun broadcastResult(connected: String?)

【讨论】:

以上是关于如何从服务获取数据到活动的主要内容,如果未能解决你的问题,请参考以下文章

从服务器获取数据时如何显示活动指示器

如何从片段获取数据到活动? [复制]

如何从片段获取数据到另一个活动? (不是容器活动)[重复]

从数据库获取活动名称并创建意图

如何使用 bundle 一次从多个活动中获取数据

无法从一个活动获取数据到另一个活动