Is it possible to check if an Android device is connected to a VPN server?
A search in the API provides 'paltform highlights' for Android 1.6, so that doesn't fill me with much confidence.
You can register to broadcastreceiver and all vpn states will come to you application.
Add this to application manifest:
<receiver android:name=".ConnectivityReceiver">
<intent-filter>
<action android:name="vpn.connectivity" />
</intent-filter>
</receiver>
create a class:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class ConnectivityReceiver extends BroadcastReceiver
{
public void onReceive(Context c, Intent intent)
{
String state = intent.getSerializableExtra("connection_state").toString();
Log.d("**************", state.toString());
if (state.equals("CONNECTING")) {
// Do what needs to be done
}
else if (state.equals("CONNECTED")) {
// Do what needs to be done
}
else if (state.equals("IDLE")) {
int errorCode = intent.getIntExtra("err", 0);
if (errorCode != 0) {
// Do what needs to be done to report a failure
}
else {
// Normal disconnect
}
}
else if (state.equals("DISCONNECTING")) {
// Usually not very interesting
}
}
}
Related
I wanted to get some experience with android IPC using AIDL. I wanted to see if it was possible to communicate between two distinct android apps.
My problem is that invoking bindService in the second app, to communicate with the first app's FactorialService, service always fails. My first app activity MainActivity which tries to call bindService always log the fact that bindService returns false. Plus MainActivity (which implements ServiceConnection) of this second app (the client app) never gets its callback method onServiceConnected called.
So, in a first application which runs a service called FactorialService
I defined an
interface, IFactorialService.aidl:
package com.simonlbc.factorialcommon;
import com.simonlbc.factorialcommon.FactorialRequest;
import com.simonlbc.factorialcommon.FactorialResponse;
interface IFactorialService {
FactorialResponse fact(in FactorialRequest r);
}
FactorialRequest contains an input number (say n). fact returns n! along with other information.
In the same application I created a class IFactorialServiceImplem
implementing that aidl interface.
package com.example.simonlbc.factorialservice;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.SystemClock;
import com.simonlbc.factorialcommon.FactorialResponse;
import com.simonlbc.factorialcommon.FactorialRequest;
public class IFactorialServiceImplem extends com.simonlbc.factorialcommon.IFactorialService.Stub {
public long recursiveFact(int n) {
if (n < 0)
throw new IllegalArgumentException("input fa");
if (n == 1 || n == 0)
return 1;
else {
return n * recursiveFact(n-1);
}
}
public long iterativeFact(int n) {
long res = 1;
for (int i = 1; i <= n; i++)
res *= i;
return res;
}
public FactorialResponse fact(FactorialRequest r) {
long timeInMillis = SystemClock.uptimeMillis();
long result = 0;
switch(r.getChoice()) {
case RECURSIVE:
result = recursiveFact(r.getInNb());
break;
case ITERATIVE:
result = iterativeFact(r.getInNb());
}
timeInMillis = SystemClock.uptimeMillis() - timeInMillis;
return new FactorialResponse(result, timeInMillis);
}
}
I then created a Service that would be used to communicate a IFactorialService instance to possible clients:
package com.example.simonlbc.factorialservice;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import com.simonlbc.factorialcommon.IFactorialService;
public class FactorialService extends Service {
private IFactorialServiceImplem s = null;
private static final String TAG = "FactorialService";
#Override
public void onCreate() {
super.onCreate();
s = new IFactorialServiceImplem();
Log.d(TAG, "onCreate'd");
}
#Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind()'d");
return this.s;
}
#Override
public boolean onUnbind(Intent intent) {
Log.d(TAG, "onUnbind()'d");
return super.onUnbind(intent);
}
#Override
public void onDestroy() {
Log.d(TAG, "onDestroy()'d");
s = null;
super.onDestroy();
}
}
the manifest of this first "service" app is the following:
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<service
android:name=".FactorialService">
<!--
android:enabled="true"
android:exported="true"
android:process=":remote"
-->
<intent-filter>
<action android:name="com.example.simonlbc.factorialservice.FactorialService" />
</intent-filter>
</service>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
the first app contains a Launcher activity which simply starts the service as so:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_service);
curPackage = getString(R.string.packageService);
MainActivity.this.startService(
new Intent()
.setAction(curPackage + ".FactorialService")
.setPackage(curPackage)
);
}
My second app's launcher activity is such as:
public class MainActivity extends Activity implements View.OnClickListener, ServiceConnection
I want MainActivity of this second app to
communicate with the first's app IFactorialService. In onResume I
try to bind with the first app's service:
#Override
protected void onResume() {
super.onResume();
Intent i = new Intent();
i.setAction("com.example.simonlbc.factorialservice.FactorialService");
i.setPackage("com.example.simonlbc");
if (!super.bindService(i, this, BIND_AUTO_CREATE))
Log.w(TAG, "Failed to bind our service!!!");
}
But it seems bindService fails. Indeed everytime I pause the app and return to it, or start it. "Failed to bind our service!!!" is displayed.
Note that the two app share an Android Library module containing the definitions of the needed aidl files.
Do you see anything that would allow bindService() to work?
Why are you using super.bindservice() ? Instead, can you try this getApplicationContext().bindservice()
Also, if this does not work either, try the following modification of your code:
Intent i = new Intent("com.example.simonlbc.factorialservice.FactorialService");
if(getApplicationContext().startService(i) != null){
if (!getApplicationContext().bindService(i, serviceConnection, 0))
Log.w(TAG, "Failed to bind our service!!!");
}
where seriveConnection is an object of service connection (I prefer not to use this for ServiceConnection ). Also, your service should have the proper Action set, otherwise it won't start
I have an Android Service that I'd like to take actions whenever the device is locked.
I'd like to clarify that:
I am not interested in the screen on/off state.
I am aware of how to use a BroadcastReceiver with Intent.ACTION_USER_PRESENT and KeyguardManager.inKeyguardRestrictedInputMode to check for when the device is unlocked.
I am not interested in a solution that requires constantly checking the lock state.
I don't want to lock or unlock the device myself.
I cannot rely on an Activity being in the foreground to handle onResume.
I add those points because I've found no end of people asking the same question and getting one of those responses. I'm happy that they did, because the answers have been useful and/or educational, but they aren't what I'm looking for now.
I've put together a potential solution, but there are some major caveats that come with it.
General approach: Detect the "screen off" event then periodically check if the device has become locked. This is far from ideal, but there does not seem to be any manner to detect when the device is locked. Basically, "there is no right way to do this so you need to hack something together".
Credit: This is based on the suggestion from #Markus in the comments combined with bits of code from the answers to the linked questions plus some extra grunt work of my own.
Caveats:
Other manufacturers may have different lock periods.
Device policy (e.g.: Android for Work) could change to enforce periods after we previously determined that the device would not lock during that period (e.g.: device could suddenly lock and we wouldn't detect for several minutes).
Device could be locked remotely by Android Device Manager.
Device could be locked by another application (e.g.: bluetooth based lock mechanism).
Untested but I suspect there are issues in this code if the user turns device
on and off quickly several times.
Untested with Doze.
Untested, but suspect there might be issues around switching users.
I have not tested this in anger, there may well be other issues.
Anyone actually using this approach should probably do a bit of a re-arch; what is presented below is just a proof of concept.
AndroidManifest.xml
Add a startup activity:
<activity android:name=".StartLockMonitorActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Add a broadcast receiver:
<receiver android:name=".StateReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
Add the main service:
<service
android:name=".LockMonitor"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="com.sample.screenmonitor.LockMonitor.ACTION_START_SERVICE"/>
</intent-filter>
</service>
Add a permission:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
res/values/styles.xml
Add transparent style:
<style name="Theme.Transparent" parent="android:Theme">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">#color/transparent</item>
<item name="android:windowContentOverlay">#null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsFloating">true</item>
<item name="android:backgroundDimEnabled">false</item>
</style>
res/values/colors.xml
Add transparent colour:
<color name="transparent">#00000000</color>
StartLockMonitorActivity.java
This is the main entry point, it just kicks the service:
package com.sample.screenmonitor;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
public class StartLockMonitorActivity extends AppCompatActivity {
public static final String TAG = "LockMonitor-SLM";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.w(TAG, "Starting service...");
final Intent newIntent = new Intent(this, LockMonitor.class);
newIntent.setAction(LockMonitor.ACTION_CHECK_LOCK);
startService(newIntent);
Toast.makeText(this, "Starting Lock Monitor Service", Toast.LENGTH_LONG).show();
finish();
}
}
StateReceiver.java
This restarts the service when the device reboots. The first time the service starts it adds some additional filters (see the comments in LockMonitor.java describing why this isn't done in the manifest).
package com.sample.screenmonitor;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class StateReceiver extends BroadcastReceiver {
public static final String TAG = "LockMonitor-SR";
#Override
public void onReceive(Context context, Intent intent) {
Log.i(TAG, "onReceive: redirect intent to LockMonitor");
final Intent newIntent = new Intent(context, LockMonitor.class);
newIntent.setAction(LockMonitor.ACTION_CHECK_LOCK);
newIntent.putExtra(LockMonitor.EXTRA_STATE, intent.getAction());
context.startService(newIntent);
}
}
LockMonitor.java
package com.sample.screenmonitor;
import android.app.KeyguardManager;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.os.PowerManager;
import android.support.annotation.Nullable;
import android.util.Log;
import java.util.Timer;
import java.util.TimerTask;
public class LockMonitor extends Service {
public static final String TAG = "LockMonitor";
public static final String ACTION_CHECK_LOCK = "com.sample.screenmonitor.LockMonitor.ACTION_CHECK_LOCK";
public static final String EXTRA_CHECK_LOCK_DELAY_INDEX = "com.sample.screenmonitor.LockMonitor.EXTRA_CHECK_LOCK_DELAY_INDEX";
public static final String EXTRA_STATE = "com.sample.screenmonitor.LockMonitor.EXTRA_STATE";
BroadcastReceiver receiver = null;
static final Timer timer = new Timer();
CheckLockTask checkLockTask = null;
public LockMonitor() {
Log.d(TAG, "LockMonitor constructor");
}
#Override
public void onDestroy() {
Log.d(TAG, "LM.onDestroy");
super.onDestroy();
if (receiver != null) {
unregisterReceiver(receiver);
receiver = null;
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "LM.onStartCommand");
if (intent != null && intent.getAction() == ACTION_CHECK_LOCK) {
checkLock(intent);
}
if (receiver == null) {
// Unlike other broad casted intents, for these you CANNOT declare them in the Android Manifest;
// instead they must be registered in an IntentFilter.
receiver = new StateReceiver();
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_USER_PRESENT);
registerReceiver(receiver, filter);
}
return START_STICKY;
}
void checkLock(final Intent intent) {
KeyguardManager keyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
final boolean isProtected = keyguardManager.isKeyguardSecure();
final boolean isLocked = keyguardManager.inKeyguardRestrictedInputMode();
final boolean isInteractive = powerManager.isInteractive();
final int delayIndex = getSafeCheckLockDelay(intent.getIntExtra(EXTRA_CHECK_LOCK_DELAY_INDEX, -1));
Log.i(TAG,
String.format("LM.checkLock with state=%s, isProtected=%b, isLocked=%b, isInteractive=%b, delay=%d",
intent != null ? intent.getStringExtra(EXTRA_STATE) : "",
isProtected, isLocked, isInteractive, checkLockDelays[delayIndex])
);
if (checkLockTask != null) {
Log.i(TAG, String.format("LM.checkLock: cancelling CheckLockTask[%x]", System.identityHashCode(checkLockTask)));
checkLockTask.cancel();
}
if (isProtected && !isLocked && !isInteractive) {
checkLockTask = new CheckLockTask(this, delayIndex);
Log.i(TAG, String.format("LM.checkLock: scheduling CheckLockTask[%x] for %d ms", System.identityHashCode(checkLockTask), checkLockDelays[delayIndex]));
timer.schedule(checkLockTask, checkLockDelays[delayIndex]);
} else {
Log.d(TAG, "LM.checkLock: no need to schedule CheckLockTask");
if (isProtected && isLocked) {
Log.e(TAG, "Do important stuff here!");
}
}
}
static final int SECOND = 1000;
static final int MINUTE = 60 * SECOND;
// This tracks the deltas between the actual options of 5s, 15s, 30s, 1m, 2m, 5m, 10m
// It also includes an initial offset and some extra times (for safety)
static final int[] checkLockDelays = new int[] { 1*SECOND, 5*SECOND, 10*SECOND, 20*SECOND, 30*SECOND, 1*MINUTE, 3*MINUTE, 5*MINUTE, 10*MINUTE, 30*MINUTE };
static int getSafeCheckLockDelay(final int delayIndex) {
final int safeDelayIndex;
if (delayIndex >= checkLockDelays.length) {
safeDelayIndex = checkLockDelays.length - 1;
} else if (delayIndex < 0) {
safeDelayIndex = 0;
} else {
safeDelayIndex = delayIndex;
}
Log.v(TAG, String.format("getSafeCheckLockDelay(%d) returns %d", delayIndex, safeDelayIndex));
return safeDelayIndex;
}
class CheckLockTask extends TimerTask {
final int delayIndex;
final Context context;
CheckLockTask(final Context context, final int delayIndex) {
this.context = context;
this.delayIndex = delayIndex;
}
#Override
public void run() {
Log.i(TAG, String.format("CLT.run [%x]: redirect intent to LockMonitor", System.identityHashCode(this)));
final Intent newIntent = new Intent(context, LockMonitor.class);
newIntent.setAction(ACTION_CHECK_LOCK);
newIntent.putExtra(EXTRA_CHECK_LOCK_DELAY_INDEX, getSafeCheckLockDelay(delayIndex + 1));
context.startService(newIntent);
}
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "LM.onBind");
return null;
}
}
I have to implement referral linking concept in my application for it, I have done some code for it. It works fine, when the application is NOT installed on my device. Means I am getting referral.
But the PROBLEM is that, I am not getting any referral when application is already installed in my device.
Here is my code which I have used to get referral.
In Manifest file.
<service android:name="com.google.android.gms.analytics.CampaignTrackingService" />
<receiver
android:name="com.tv.testing.utils.InstallReceiver"
android:exported="true" >
<intent-filter>
<action android:name="com.android.vending.INSTALL_REFERRER" />
</intent-filter>
</receiver>
In my Java class
package com.tv.testing.utils;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.widget.Toast;
import com.tv.testing.BuildConfig;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
public class InstallReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String rawReferrer = intent.getStringExtra("referrer");
System.out.println("Here is the REFFEREAL first works for us====>>"+rawReferrer);
if (rawReferrer != null) {
trackReferrerAttributes(rawReferrer, context);
}
}
private void trackReferrerAttributes(String rawReferrer, Context context) {
String referrer = "";
try {
referrer = URLDecoder.decode(rawReferrer, "UTF-8");
} catch (UnsupportedEncodingException e) {
return;
}
System.out.println("Here is the REFFEREAL SECOND works for us====>>"+referrer);
Toast.makeText(context ,"Install reference ==>> "+referrer, Toast.LENGTH_SHORT).show();
}
}
Is there any other way to get referral when the application is already installed on my device?
I have looked more than 2 hours for a solution, but no chance.
I have installed parse into my application android and I have installed it in my phone (android s4 mini, using wifi currently).
Here is how my parse is setup in my project:
Parse.initialize(mInstance, App.parseAppId, App.parseAppKey);
// Specify an Activity to handle all pushes by default.
PushService.setDefaultPushCallback(mInstance, MainActivity.class);
ParseInstallation.getCurrentInstallation().saveInBackground();
I see that parse logged my installation
http://awesomescreenshot.com/0865kofmd9
But when I send a push, my app crash "Unfortunately Application has stopped working"
Here is my androidmanifest:
http://pastebin.com/UySbvP8P
Any advise please?
Thanks
Please try to replace the default parse push receiver with this: :
remove:
PushService.setDefaultPushCallback(mInstance, MainActivity.class);
AndroidManifest.xml:
<receiver
android:name="ParsePushReceiver"
android:exported="false">
<intent-filter>
<action android:name="com.parse.push.intent.RECEIVE"/>
<action android:name="com.parse.push.intent.DELETE"/>
<action android:name="com.parse.push.intent.OPEN"/>
</intent-filter>
</receiver>
ParsePushReceiver.java:
import android.content.Context;
import android.content.Intent;
import com.parse.ParsePushBroadcastReceiver;
public class ParsePushReceiver extends ParsePushBroadcastReceiver {
#Override
public void onPushOpen(Context context, Intent intent) {
Intent newIntent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
newIntent.putExtras(intent.getExtras());
context.startActivity(newIntent);
}
}
App.java
#Override
public void onCreate() {
super.onCreate();
Parse.initialize(this, parseAppId, parseAppKey);
if (ParseInstallation.getCurrentInstallation() != null && ParseInstallation.getCurrentInstallation().getCreatedAt() == null) {
ParseInstallation.getCurrentInstallation().saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if (e != null) {
//track error
}
}
});
}
mInstance = this;
if (isOnline()) {
makeJsonObjectRequest();
}
}
I try to implement the network receiver, here is my following code:
package com.example.androidtablayout;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.util.Log;
public class NetworkReceiver extends BroadcastReceiver { // <1>
public static final String TAG = "NetworkReceiver";
boolean isConnected = true;
Context c;
#Override
public void onReceive(Context context, Intent intent) {
boolean isNetworkDown = intent.getBooleanExtra(
ConnectivityManager.EXTRA_NO_CONNECTIVITY, false); // <2>
if (isNetworkDown) {
Log.d(TAG, "onReceive: NOT connected, stopping UpdaterService");
// context.stopService(new Intent(context, UpdaterService.class)); // <3>
} else {
Log.d(TAG, "onReceive: connected, starting UpdaterService");
// context.startService(new Intent(context, UpdaterService.class)); // <4>
}
}
}
In the Manifest.xml
<application>
<receiver android:name=".NetworkReceiver">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
</application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
My problem is when I switch off the wifi, the log still shows that "Connected",
I think the the network receiver didn't receiver the intenet connectivity correctly.Any help will be greatly appreciated.
Here is a sample class that shows you how to do it. I think this is exactly what you need and it might help resolve your issue. In this sample the BroadcastReceiver is registered programmatically instead of the Manifest, but I think it won't be a problem for you.
Let me know if works.