Android :get an object from an inner class - android

I defined a broadcast receiver as an inner class .And i wan't to get an object from the receiver to the external class ,jut like this :
class External {
public object ;
class Inner {
object = something ;
getObject () { return object; }
}//end Inner class
method (){
Inner inn = new Inner();
inn.getObject(); //here i would like to get the object from inner class
}
}
But it doesent work for me , i'm gettin an empty object ,this is my real code :
public class Wifi extends Activity implements OnClickListener{
/** Called when the activity is first created. */
WifiManager wifi;
Button enab;
String resultsString ;
String[] myStringArray;
public class Receiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)){
List<ScanResult> results = wifi.getScanResults();
resultsString = results.toString() ;
//Log.i("resultsString",resultsString);
List<WifiConfiguration> resultsConf = wifi.getConfiguredNetworks();
}
}
/***** I would like to get resultsString *******/
public String getResult(){
return resultsString ;
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_wifi);
ConnectivityManager cxMgr = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
wifi = (WifiManager)getSystemService(Context.WIFI_SERVICE);
Receiver receiver = new Receiver();
/***** I would like to get resultsString in this method but I'm getting a null **/
registerReceiver(receiver,new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
registerReceiver(receiver,new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
Log.i("receiver.getResult()",receiver.getResult()+"");
}
}
And this is my logCat
03-27 12:28:51.947: I/receiver.getResult()(24524): null
Thank you .I home someone will help me :)

Try this..
I guess your getting error in below line
Log.i("receiver.getResult()",receiver.getResult());
may be receiver is null so that you can check it like below add ""+
Log.i("receiver.getResult()",""+receiver.getResult());
EDIT:
IntentFilter intentFilter =new IntentFilter(Receiver.ACTION_TEXT_CAPITALIZED);
intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
/* create new broadcast receiver*/
Receiver receiver = new Receiver();
registerReceiver(receiver, intentFilter);
Add this in your Receiver class
public final static String ACTION_TEXT_CAPITALIZED= "com.android.guide.exampleintentservice.intent.action.ACTION_TEXT_CAPITALIZED";
You can send information like below
Intent resultBroadCastIntent =new Intent();
resultBroadCastIntent.setAction(Receiver.ACTION_TEXT_CAPITALIZED);
resultBroadCastIntent.setAction(ConnectivityManager.CONNECTIVITY_ACTION);
resultBroadCastIntent.setAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
resultBroadCastIntent.addCategory(Intent.CATEGORY_DEFAULT);
sendBroadcast(resultBroadCastIntent);

Related

Data Binding from Android project to ViewModel

I am trying to get list of available wifi network and display it in a list view. In PCL project, i created an interface 'IWifiService'.
public interface IWifiService
{
void GetWifiList();
}
In android project a class WifiService to get all networks list.
[assembly:Dependency(typeof(WifiService))]
namespace WifiConnectivity.Droid.WifiService
{
public class WifiService : IWifiService
{
private static WifiManager wifi;
private WifiReceiver wifiReceiver;
public static List<string> WiFiNetworks;
public void GetWifiList()
{
WiFiNetworks = new List<string>();
var context = Android.App.Application.Context;
wifi = (WifiManager)context.GetSystemService(Context.WifiService);
wifiReceiver = new WifiReceiver();
context.RegisterReceiver(wifiReceiver, new IntentFilter(WifiManager.ScanResultsAvailableAction));
wifi.StartScan();
}
public class WifiReceiver : BroadcastReceiver
{
public override void OnReceive(Context context, Intent intent)
{
IList<ScanResult> scanWifiNetworks = wifi.ScanResults;
foreach(ScanResult wifinetwork in scanWifiNetworks)
{
WiFiNetworks.Add(wifinetwork.Ssid);
}
}
}
}
}
And from ViewModel i am calling a Dependency Service like this:
var service = DependencyService.Get<IWifiService>();
service.GetWifiList();
Now the class WifiReceiver cannot return anything, so i am not being able to get those list of networks in my ViewModel. How can i get this list into my ViewModel?
I would suggest that you return a List in your GetWifiList method so the interface looks something like this:
public interface IWifiService
{
void GetWifiList(Action<List<string>> action);
}
And then your GetWifiList method will look like this:
public static Action<List<string>> CallBackAction;
public void GetWifiList(Action<List<string>> callBackMethod)
{
WiFiNetworks = new List<string>();
var context = Android.App.Application.Context;
wifi = (WifiManager)context.GetSystemService(Context.WifiService);
wifiReceiver = new WifiReceiver();
context.RegisterReceiver(wifiReceiver, new IntentFilter(WifiManager.ScanResultsAvailableAction));
wifi.StartScan();
CallBackAction= callBackMethod;
}
And then in your OnRecieve method, you execute the callback method:
public override void OnReceive(Context context, Intent intent)
{
IList<ScanResult> scanWifiNetworks = wifi.ScanResults;
foreach(ScanResult wifinetwork in scanWifiNetworks)
{
WiFiNetworks.Add(wifinetwork.Ssid);
}
CallBackAction(WiFiNetworks);
}
And now the most important part of the callback method and what to pass as your argument:
A System.Action is basically a method reference where you pass the name of your call back method something like below:
var service = DependencyService.Get<IWifiService>();
service.GetWifiList(MyCallBackAction);
Where MyCallBackAction is as below:
public void MyCallBackAction(List<string> wifiNetworks)
{
// this method will be called every time you get a callback at OnRecieve
}

Android invoke interface inside class file in lib module

Hi in my lib module I'm having a interface like this,
public interface ServiceData {
void deviceName();
}
I implement this in Main app module in Activity as follows,
MainActivity extends AppCompatActivity implements ServiceData
#Override
public void deviceName() {
}
}
I have to invoke this in a class file which is also in lib module. I searched and found solution like
ServiceData service = (ServiceData) context;
But it throws ClassCastException. How can I invoke this in a class file? Any help will be appreciated and thanks in advance.
Use localbroadcastmanager.
In lib
Intent intent = new Intent("YOUR_INFO");
LocalBroadcastManager manager = LocalBroadcastManager.getInstance(context);
manager.sendBroadcast(intent);
In app.
IntentFilter intentFilter = new IntentFilter("YOUR_INFO");
LocalBroadcastManager manager = LocalBroadcastManager.getInstance(this);
manager.registerReceiver(broadcastReceiver, intentFilter);
private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.d("MainActivity","your info" +" "+action);
if(action.equals("YOUR_INFO")) {
}
}
};

Download data from internet in background and concurrently share them among all activities. How?

I need to download elements from internet and add them to an arraylist in the background. (The download may take a few minutes.)
There is a loop in which part of overall elements are downloaded each iteration and added to the list. I need different activities be able to have access to that arraylist whenever needed, no matter if the download (the loop) is in progress or finished.
It seems a service can do this, but i don't have any idea on how. Considering the code below, how can i achieve this?
class A extends Service {
void foo(){
//uses a loop to get elements from internet
//then adds the elements to myArraylist in each loop
}
}
class B extends Activity {
//needs to have access to myArraylist asynchronously
}
class C extends Activity {
//needs to have access to myArraylist asynchronously
}
Note that i need the download process stay active when user switches between activities.
You can do it by Broadcast receiver.For send the data on other activity you can use:
intent = new Intent(ApplicationSetting.NEW_MESSAGE_ACTION);
intent.putExtra(IMMessage.IMMESSAGE_KEY, msg);
sendBroadcast(intent);
For receive this message for other any activity you can use this code:
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
/*
* For before commit
*/
if (ApplicationSetting.NEW_MESSAGE_ACTION.equals(action)) {
IMMessage message = intent
.getParcelableExtra(IMMessage.IMMESSAGE_KEY);
Log.w("message", "are" + message);
}
}
};
So the problem you face with what you are asking is that your download loop may be adding to or changing the list while the active activity may also be accessing the same list. This can cause a ConcurrentModificationException. To avoid this what you need to do is synchronise all activity with the list. In order to make it available to all activities and have it accessible to your service I would suggest that the list itself is stored in your application (a class extending Application)
public class MyApplication extends Application {
private List<MyElement> mElems;
#Override
public void onCreate() {
super.onCreate();
mElems = Collections.synchronizedList(new ArrayList<MyElement>());
//this line will start your download service, available accross the whole app
startService(new Intent(getApplicationContext(), A.class));
}
//You can use accessor methods and keep the list private to ensure
//synchronisation doesn't get missed anywhere
public void synchronisedAddElement(MyElement elem) {
mElems.add(elem); //already synchronous in this case
}
//I havent tested this method, you method below may be safer
public Iterator getElementsIteratorSynchronised() {
synchronized(mElems) {
return list.iterator();
}
}
public Iterator iterateElementsSynchronised(OnElementListener lis) {
synchronized(mElems) {
Iterator<MyElement> i = list.iterator();
if (lis != null) {
while (l.hasNext()) {
lis.onElement(l.next());
}
}
}
}
public static class OnElementListener {
public void onElement(MyElement el);
}
}
You would write to it as follows
class A extends Service {
void foo(){
MyApplication app = (MyApplication) getApplication();
... //do your network call loop here, adding to local list
app.synchronisedAddElement( myNewElement );
}
}
And Read
class B extends Activity {
//the async task just because your comment said async access
new AsynTask<MyApplication, Void, Void>() {
public Void doInBackground(MyApplication app) {
app.iterateElementsSynchronised(new OnElementListener() {
public void onElement(MyElement el) {
Log.d(TAG, "Did somethign appropriate with " + el);
}
})
}
}.execute( (MyApplication) getApplication() );
}
Please just treat this as pseudo code, I've written it on the train home so the method signatures may vary, but this should get you where you need to be
Using the structure recommended by Nick Cardoso but with many changes to meet my case, i managed to solve the problem. here it is:
class A extends Service {
ArrayList arrayList = new ArrayList();
MyApplication app;
void foo(){
new Thread (new Runnable (){
#Override
public void run() {
app = (MyApplication)getApplication();
While(true){
//get elements from network and put them in arrayList
app.synchronisedAddCollection(arrayList);
LocalBroadcastManager.getInstance(this).sendBroadcast(mediaIntent);
}
}
}).start();
}
}
And here is my Application class:
public class MyApplication extends Application {
List<HashMap<String, String>> myArrayList = new ArrayList<HashMap<String, String>>();
#Override
public void onCreate() {
super.onCreate();
}
public void synchronisedAddCollection(ArrayList<HashMap<String, String>> arrayList) {
myArrayList.addAll(arrayList);
}
public ArrayList<HashMap<String, String>> getArrayList(){
return (ArrayList<HashMap<String, String>>) myArrayList;
}
}
Here is the activity which needs to access the shared arraylist
class B extends Activity {
MyApplication app;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
startService(new Intent(getApplicationContext(), MyService.class);
LocalBroadcastManager.getInstance(this).registerReceiver(lbr,
new IntentFilter("mediaIntent"));
}
private BroadcastReceiver lbr = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
app = (MyApplication)getApplication();
//now i have access to the app arrayList
System.out.println(app.myArrayList.size());
}
}
};
}
Do not forget to register MyApplication and MyService in manifest.

How to make dynamically registered receive from outside of activity ?

I have a class structure as below
public class Admin extends DeviceAdminReceiver
{
public static class PubSub extends Activity
{
protected void onCreate(Bundle savedInstanceState) {
messageIntentReceiver = new MQTTMessageReceiver();
IntentFilter intentCFilter = new IntentFilter(MQTTService.MQTT_MSG_RECEIVED_INTENT);
registerReceiver(messageIntentReceiver, intentCFilter);
}
#Override
protected void onDestroy()
{
unregisterReceiver(messageIntentReceiver);
super.onDestroy();
}
public class MQTTMessageReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
Bundle notificationData = intent.getExtras();
String newTopic = notificationData.getString(MQTTService.MQTT_MSG_RECEIVED_TOPIC);
String newData = notificationData.getString(MQTTService.MQTT_MSG_RECEIVED_MSG);
Log.e("Received Message on",newTopic+"- "+newData);
}
}
}
}
The receivers are dynamically registered and unregistered. The broadcast receiver works while PubSub activity stays on the screen. How to make it work from outside of activity?
I tried to do it in static way by registering in manifest.xml, but that dint work as MQTTMessageReceiver is a non static inner class. Cant able to instantiate the receiver runtime error I get.
I cant change the MQTTMessageReceiver class static as i need to access outer class members.

The right way to dynamically control location tracking (registering / unregistering location broadcast receiver)

I want to dynamically control location tracking (registering / unregistering location broadcast receiver). This is how I am planning to do it. I have two questions :
What are the mistakes in the implementation below because all this concept is still very theoretical to me as I am very new to android/java dev. Still building concepts!
How do I pass some EXTRA_INFO from my location library class to the location receiver.
IMPLEMENTATION:
I have a library class LocationLibrary.java which consists of two methods. They do as the name suggest. The location tracking should start when I call startTracking(). Plz note the extraInfo that needs to be passed to myLocationReceiver. The tracking should stop when stopTracking() is called.
Code snippet:
public class LocationLibraray
{
private static BroadcastReceiver myLocationReceiver;
public LocationLibraray(Context context)
{
this.ctx = context;
myLocationReceiver = new MyLocationReceiver();
}
public void startTracking(Context context, String extraInfo)
{
IntentFilter filter = new IntentFilter();
filter.addAction("com.app.android.tracker.LOCATION_READY");
context.registerReceiver(myLocationReceiver, filter);
// NEED TO PASS extraInfo to myLocationReceiver for some processing, but HOW?
}
public void stopTracking(Context context)
{
context.unregisterReceiver(locationReceiver);
}
}
MyLocationReceiver.java
public class MyLocationReceiver extends BroadcastReceiver {
public void onReceive(final Context context, Intent intent) {
if ((intent.getAction() != null) &&
(intent.getAction().equals("com.app.android.tracker.LOCATION_READY")))
{
//GET THAT EXTRA INFO FROM LocationLibrary class and process it here
}
}
}
Please help me out. Thnx!
Why not add a constructor to MyLocationReceiver?
public class MyLocationReceiver extends BroadcastReceiver {
String info = "";
public MyLocationReceiver(String extraInfo)
{
this.info = extraInfo;
}
........
public void onReceive(final Context context, Intent intent) {
if ((intent.getAction() != null) &&
(intent.getAction().equals("com.app.android.tracker.LOCATION_READY")))
{
if (info.contains("Hi"))
//do some stuff
}
}
}
And you would instantiate it like this:
myLocationReceiver = new MyLocationReceiver(new String("Hello!"));

Categories

Resources