Keeping Wifi-Direct Turned on AOSP devices - android

My friend and I are developing an app that streams synchronized music between android devices using wifi-direct. Our issue is that while the app works fairly well once phones are connected, it takes some doing to get phones to connect because on all AOSP devices it appears that wifi direct is only turned on upon entering the wifi direct menu (and immediately closed upon exiting). This makes in-application connection rather difficult. We were wondering if there is any way to turn on wifi direct from the code and keep it on (if anyone could refer us to a detailed description of how to do this using Reflection that would be fantastic).
Thanks! Here is our current code:
public class Reflector {
static Method turnOnICS;
static Method turnOnJB;
static Method turnOffICS;
public static void turnOnP2P(WifiP2pManager m, Channel c) {
//Log.v("button", "turnOnP2P");
if (android.os.Build.VERSION.SDK_INT == 14 || android.os.Build.VERSION.SDK_INT == 15) {
//Log.v("version", "Version is ICS");
try {
turnOnICS = WifiP2pManager.class.getDeclaredMethod("enableP2p",WifiP2pManager.Channel.class);
turnOnICS.setAccessible(true);
turnOnICS.invoke(m, c);
} catch (NoSuchMethodException e) {
Log.v("ics_error", "ICS enableP2p() not found");
} catch (Exception e) {
Log.v("ics_error", "turnOnICS invocation failure");
}
} else if (android.os.Build.VERSION.SDK_INT == 16 || android.os.Build.VERSION.SDK_INT == 17) {
//Log.v("version", "Version is JB");
try {
turnOnJB = NsdManager.class.getDeclaredMethod("setEnabled", boolean.class);
turnOnJB.setAccessible(true);
turnOnJB.invoke(NsdManager.class, true);
//must feed it an nsdmanager, but none exists in wifidirectactivity
Log.v("nsd", "problem");
} catch (NoSuchMethodException e) {
Log.v("jb_error", "JB setEnabled() not found");
} catch (Exception e) {
Log.v("jb_error", "turnOnJB invocation failure");
e.printStackTrace();
}
}
}
public static void turnOffP2P(WifiP2pManager m, Channel c) {
//Log.v("button", "turnOffP2P");
if (android.os.Build.VERSION.SDK_INT == 14 || android.os.Build.VERSION.SDK_INT == 15) {
//Log.v("version", "Version is ICS");
try {
turnOffICS = WifiP2pManager.class.getDeclaredMethod("disableP2p", WifiP2pManager.Channel.class);
turnOffICS.setAccessible(true);
turnOffICS.invoke(m, c);
} catch (NoSuchMethodException e) {
Log.v("ics_error", "ICS disableP2P() not found");
} catch (Exception e) {
Log.v("ics_error", "turnOffICS invocation failure");
}
}
}
public static void printAll(){
Method[] list = WifiP2pManager.class.getDeclaredMethods();
for(Method m : list){
Log.v("tag",m.getName());
}
}
}

Thank you for asking this question... it's been a question we've been wrestling with as we add WiFi Direct features to our app.
After looking through the settings on several phones from different manufacturers, and reading pages like this and this (which admittedly are not very precise in the details, but it's the best we could find), we've come to the conclusion that there's no need to separately turn on WiFi Direct per se: it's enabled whenever WiFi is enabled. So, at most, your app would need to turn on WiFi.
However, WiFi Direct scanning (and visibility to being scanned) is what you initiate by going to the WiFi Direct settings page.
Leaving that page may stop the scanning (though 3rd-party apps can and do initiate their own scanning), but should not disable WiFi Direct. That would make no sense at all... as you say, that would make it difficult (impossible) for apps to use WiFi Direct, but apps do use it successfully. What did you see that made it seem like WiFi Direct was being disabled when you left that settings page?

Related

How do I programmatically dismiss a crash dialog?

I'm building a DPC (Device Policy Controller), and one of the issues I'm seeing is that while the Play Store and Play Services are being updated, the Google Contact Sync service crashes -- leaving the typical crash dialog on the screen. Since part of the idea of the initial set up process is to have as little user interaction as possible, how can I dismiss this dialog programmatically (since I seem to be pretty much guaranteed that this will happen)?
I've tried dismissing system dialogs...
ctx.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
... but that doesn't seem to do the trick.
Since this is a DPC, anything that requires device ownership/administration is fine.
edit: Usually I have no UI on screen at the time, so if one is necessary please do mention it. Also, preferably the solution should work on at least 6.0+, if not 4.0+.
Try to do it onWindowsFocusChanged method like this for example :
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (!hasFocus) {
Intent ctx= new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
sendBroadcast(ctx);
}
}
I'm not sure about app crash Dialog but maybe it'll help you
AppErrorDialog can be dismissed by broadcasting ACTION_CLOSE_SYSTEM_DIALOGS if Android version is N.
ctx.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
However, AppErrorDialog won't be displayed if phone is locked.
public boolean canShowErrorDialogs() {
return mShowDialogs && !mSleeping && !mShuttingDown
&& mLockScreenShown != LOCK_SCREEN_SHOWN;
} // ActivityManagerService
Please try this code.
try {
Class ActivityManagerNative = Class.forName("android.app.ActivityManagerNative");
Class IActivityManager = Class.forName("android.app.IActivityManager");
Method getDefault = ActivityManagerNative.getMethod("getDefault", null);
Object am = IActivityManager.cast(getDefault.invoke(ActivityManagerNative, null));
Method closeSystemDialogs = am.getClass().getMethod("closeSystemDialogs", String.class);
closeSystemDialogs.invoke(am, "DPC close");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}

How to call an Android app's method remotely?

I'm working on a project that improves Automation Test for Android's App. What I want to do is very "easy": I have this very simple SIP Client with a basic UI and developed just reading the API guides on the android developer website (https://developer.android.com/guide/topics/connectivity/sip.html) that receives and makes SIP calls.
I need to control remotely this app from my PC, connected at the same local network or the same wifi, by sending commands or similar (without interact with the phone) to the app itslef running normally on my phone.For a specific example I posted the method initiateCall() that calls sipAddress(in the app, sipAddress is taken from a Text Box), what I want to do is:
Starting the app on my phone
calling the method initiateCall() from my pc giving a sipAddress as a parameter (I must not use the UI from the app running, that's why I need to give the sipAddress)
check if an outgoing call starts from the app running on my phone
I thought that the solution must be something about web-services,but I don't have any better ideas and i don't know how to start and where to start solving this problem,that's why i need you help.
public void initiateCall() {
try {
SipAudioCall.Listener listener = new SipAudioCall.Listener() {
// set up the listener for outgoing calls
#Override
public void onCallEstablished(SipAudioCall call) {
call.startAudio();
call.setSpeakerMode(true);
updateStatus(call, 2);
}
#Override
public void onCallEnded(SipAudioCall call) {
updateStatus("Call End");
}
};
call = manager.makeAudioCall(me.getUriString(), sipAddress,
listener, 30);
} catch (Exception e) {
Log.i("WalkieTalkieActivity/InitiateCall",
"Error when trying to close manager.", e);
if (me != null) {
try {
manager.close(me.getUriString());
} catch (Exception ee) {
Log.i("WalkieTalkieActivity/InitiateCall",
"Error when trying to close manager.", ee);
ee.printStackTrace();
}
}
if (call != null) {
call.close();
}
}
}
You could do it REST API style. You would need to set up a minimalistic webserver.
If you access for example the url phoneip/ctrl/makecall?number=yournumber a serverside method us called if set up correctly. Then you can call you method and use the GET or POST variables as arguments.
You would have to look into Java Webserver Libraries/Frameworks. You can pick a lightweight one for that purpose. For example this one.
You could then also add security features (authentification to protect it) quite easily.
Example with sparkjava
import static spark.Spark.*;
....
get("/ctrl/makecall", (request, response) -> {
String phonenum = request.queryParams("number"); //may not be accurate; you have to determine the GET variable called "number" in that case; you can rename it; see docs!!!
//call your method with proper arguments
});

dual sim android phone which sim receive a call

I have an android application that detect the incoming calls, i need to improve this app to work on a duos mobile device.
so i create a broadcast receiver registered in manifest for actions: phone state changed and on my onReceive method i need to check which sim receive the call. This is my code
Protected void onReceive(Context c, Intent i)
{
Int whichSim = intent
getIntExtra("simSlot",-1);
// so this methof return 0 for sim 1 and 1 for sim2
If(whichSim==-1)
WhichSim=intent.getIntExtra("com.androie.phone.extra.slot",-1);
}
I run this app on a device 4.2
2 and its working normally but when i run it on a device 4
4.4 so this method does not work, i mean that which sim return -1 in all cases. Can anyone help me?
Android does not support dual sim phone until Android 5.1 and therefore any extension to support it may be device and version specific. The following is specific for the class of phones using a variant of MultiSimTelephonyManager to handle dual sims, including Samsung duos galaxy J1 under Android 4.4.4.
Basically this class of dual sim phones use two instances of MultiSimTelephonyManager, subclassed from the regular TelephonyManager and each responsible for one SIM slot, as an interface to control the phone.
One of the means to detect the incoming call is to use the PhoneStateListener class (instead of using a receiver) to detect change in phone states. The PhoneStateListener in these phones are modified (rather than subclassed) to include a mSubscription field which should indicate the SIM slot of the listener.
Both the MultiSimTelephonyManager class and the mSubscription field of PhoneStateListener are not in the standard SDK. To compile the app to use these interface, Java Reflection is needed.
The following code should roughly illustrate how you could get the sim slot information from incoming calls. I do not have the device to test, so the code may need refinements.
Set up the listener during your initialization stage -
try {
final Class<?> tmClass = Class.forName("android.telephony.MultiSimTelephonyManager");
// MultiSimTelephonyManager Class found
// getDefault() gets the manager instances for specific slots
Method methodDefault = tmClass.getDeclaredMethod("getDefault", int.class);
methodDefault.setAccessible(true);
try {
for (int slot = 0; slot < 2; slot++) {
MultiSimTelephonyManager telephonyManagerMultiSim = (MultiSimTelephonyManager)methodDefault.invoke(null, slot);
telephonyManagerMultiSim.listen(new MultiSimListener(slot), PhoneStateListener.LISTEN_CALL_STATE);
}
} catch (ArrayIndexOutOfBoundsException e) {
// (Not tested) the getDefault method might cause the exception if there is only 1 slot
}
} catch (ClassNotFoundException e) {
//
} catch (NoSuchMethodException e) {
//
} catch (IllegalAccessException e) {
//
} catch (InvocationTargetException e) {
//
} catch (ClassCastException e) {
//
}
Override PhoneStateListener and set the mSubscription field to listen to phone state changes:
public class MultiSimListener extends PhoneStateListener {
private Field subscriptionField;
private int simSlot = -1;
public MultiSimListener (int simSlot) {
super();
try {
// Get the protected field mSubscription of PhoneStateListener and set it
subscriptionField = this.getClass().getSuperclass().getDeclaredField("mSubscription");
subscriptionField.setAccessible(true);
subscriptionField.set(this, simSlot);
this.simSlot = simSlot;
} catch (NoSuchFieldException e) {
} catch (IllegalAccessException e) {
} catch (IllegalArgumentException e) {
}
}
#Override
public void onCallStateChanged(int state, String incomingNumber) {
// Handle the event here, with state, incomingNumber and simSlot
}
}
You will also need to create a file named MultiSimTelephonyManager.java at the [project]/src/android/telephony directory.
package android.telephony;
public interface MultiSimTelephonyManager {
public void listen(PhoneStateListener listener,int events);
}
You should probably do some error checking and especially check if the phone is the target model, when using the code.
Please be warned (again) that the above would not work in most other phones and other Android versions of the same phone.
This question suggests "com.android.phone.extra.slot" may also work on some phones. Maybe try both and use the one that didn't return -1?
Have you Try this Method :-
in this method you will get 0 for 1 Sim and for second sim you will get 1.
//Working code For 4.4 Phones KitKat
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
whichSIM = intent.getExtras().getInt("subscription");
if (whichSIM == 0) {
whichSIM = 1;
editor.putLong("ChooseSim", whichSIM);
editor.commit();
// Incoming call for SIM1
} else if (whichSIM == 1) {
whichSIM = 2;
editor.putLong("ChooseSim", whichSIM);
editor.commit();
}

How to use the hide methods in API?

I have seen some hide methods in
/** #hide */
public void setDiscoverableTimeout(int timeout) {
if (getState() != STATE_ON) return;
try {
mService.setDiscoverableTimeout(timeout);
} catch (RemoteException e) {Log.e(TAG, "", e);}
}
I want to use the above method but still not aware that how can I use this method in my program so that my app should be always in discoverable mode?
you can use reflections, i have been using it. The only flip side is it may be google doesn't provide any guarantee for it.

Exception when trying to call(SIP)

I'm developping a SIP application, and when i want to call someone(with its identifier configured in the server) i have a NullPointerException => "Error when trying to close manager."
Here is the code:
public void initiateCall() {
updateStatus(sipAddress);
try {
SipAudioCall.Listener listener = new SipAudioCall.Listener() {
#Override
public void onCallEstablished(SipAudioCall call) {
call.startAudio();
call.setSpeakerMode(true);
call.toggleMute();
updateStatus(call);
}
#Override
public void onCallEnded(SipAudioCall call) {
updateStatus("Ready.");
}
};
call = manager.makeAudioCall(me.getUriString(), sipAddress, listener, 30);
}
catch (Exception e) {
Log.i("WalkieTalkieActivity/InitiateCall", "Error when trying to close manager.", e);
if (me != null) {
try {
manager.close(me.getUriString());
} catch (Exception ee) {
Log.i("WalkieTalkieActivity/InitiateCall",
"Error when trying to close manager.", ee);
ee.printStackTrace();
}
}
if (call != null) {
call.close();
}
}
}
Thank you for your help.
The VOIP/SIP libary is not supported by default on Android emulator. The problem is that the manager == null - thats why you are getting the NullPointerException.
Luckily, there is a work-a-round. Download this link and copy it into ...\.android\avd\.avd folder.
Start your emulator and
Boolean voipSupported = SipManager.isVoipSupported(this);
Boolean apiSupported = SipManager.isApiSupported(this);
should now return true.
Source: http://xilard.hu/
Android.net.sip (Sip API) only works on G711 over Android 2.3+.
Also the phones supplied by carriers may have the SIP stack (android.net.sip) blocked or cripple. SipManager.isVoipSupported(this) && SipManager.isApiSupported(this) will return false for most of the devices is your ie. your SipManager object will always be null in such case.You should use third party library to implement SIP.
There are different open source sip stack libraries as well as projects are available on internet. You can download the source code of that projects.
Here is the List of some popular open source sip stack libraries which allows to voice call over internet.
1.Jain sip (I think the best option):
2.Pjsip
3.Mjsip
4.Doubango
There are different open source projects which have used these libraries in their projects.
1.Jain sip: Not used in a "famous" app.
2. Sipdroid uses MjSip
3. Csipsimple uses PjSip
4. Imsdroid uses doubango.
Check the bridge connection in Android and the SIP server in your application to obtain the SIP key of your application.

Categories

Resources