Broadcast receiver is not calling on internet connectivity check - android

I am trying to make a simple app which will notify if there is internet connection available or not on internet connectivity change. i have found some solution on internet and tries to implement them but somehow its not working. my broadcast receiver which i have registered on my manifest file is not calling on network connectivity change.
Manifest
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".NetworkStateChangeReceiver">
<intent-filter >
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
</application>
Broadcast Receiver
package com.gdm.internetconnectivitycheck;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import static android.content.Context.CONNECTIVITY_SERVICE;
public class NetworkStateChangeReceiver extends BroadcastReceiver {
public static final String NETWORK_AVAILABLE_ACTION = "com.gdm.retailalfageek.NetworkAvailable";
public static final String IS_NETWORK_AVAILABLE = "isNetworkAvailable";
#Override
public void onReceive(Context context, Intent intent) {
Intent networkStateIntent = new Intent(NETWORK_AVAILABLE_ACTION);
networkStateIntent.putExtra(IS_NETWORK_AVAILABLE, isConnectedToInternet(context));
LocalBroadcastManager.getInstance(context).sendBroadcast(networkStateIntent);
Log.e("Network Available ", "On receive called");
}
private boolean isConnectedToInternet(Context context) {
try {
if (context != null) {
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
return networkInfo != null && networkInfo.isConnected();
}
return false;
} catch (Exception e) {
Log.e(NetworkStateChangeReceiver.class.getName(), e.getMessage());
return false;
}
}
}
Main Activity
package com.gdm.internetconnectivitycheck;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.design.widget.Snackbar;
import static com.gdm.internetconnectivitycheck.NetworkStateChangeReceiver.IS_NETWORK_AVAILABLE;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
IntentFilter intentFilter = new IntentFilter(NetworkStateChangeReceiver.NETWORK_AVAILABLE_ACTION);
LocalBroadcastManager.getInstance(this).registerReceiver(new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
boolean isNetworkAvailable = intent.getBooleanExtra(IS_NETWORK_AVAILABLE, false);
String networkStatus = isNetworkAvailable ? "connected" : "disconnected";
Snackbar.make(findViewById(R.id.main_activity), "Network Status: " + networkStatus, Snackbar.LENGTH_LONG).show();
}
}, intentFilter);
}
}

Apps targeting Android 7.0 (API level 24) and higher must register the
following broadcasts with
registerReceiver(BroadcastReceiver,IntentFilter)
Declaring a receiver in the manifest does not work.
CONNECTIVITY_ACTION
Beginning with Android 8.0 (API level 26), the
system imposes additional restrictions on manifest-declared receivers.
If your app targets API level 26 or higher, you cannot use the
manifest to declare a receiver for most implicit broadcasts
(broadcasts that do not target your app specifically). You can still
use a context-registered reciever when the user is actively using your
app.
directly from official doc.
you need to register for CONNECTIVITY_CHANGE action at runtime from activity.
using registerReceiver.
IntentFilter filter = new IntentFilter();
filter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
registerReceiver(new NetworkStateChangeReceiver(), filter);
And don't forget to unregister.

Related

React native clipboard listener service for android

I am working on an app in react native. I am searching for a code when my app is in the background or has killed. I want a service like notifcationListnerService which invokes the app again. want a similar service that is always running and when a user copies something it will show a push notification to the user like that you have copied something.
Here is what I have tried but these are too complex to understand because these are in java.
Android ClipBoard Manager
Android ClipBoard With Example
This question from StackOverflow also does not have any answer
A solution for GitHub but too complex
one thing I didn't need #react-native-community/clipboard or something like this. the thing that I need is to show push notification on copying something for any app installed of the device.
So Finally searching for two days finally I have implemented what I want. I am showing a toast, not a notification(will implement it later). I am sharing my code but still, I have a problem when my application restart its service for clipboard manager the service is running as I see it in the logcat. Here is my code.
ClipboardMonitorService.java
package com.wm;
import android.app.Service;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Intent;
import android.os.Environment;
import android.os.IBinder;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.Date;
public class ClipboardMonitorService extends Service {
private static final String TAG = "ClipboardManager";
private static final String FILENAME = "clipboard-history.txt";
private File mHistoryFile;
private ExecutorService mThreadPool = Executors.newSingleThreadExecutor();
private ClipboardManager mClipboardManager;
#Override
public void onCreate() {
super.onCreate();
Log.e("service is running","service is running");
// TODO: Show an ongoing notification when this service is running.
mHistoryFile = new File(getExternalFilesDir(null), FILENAME);
mClipboardManager =
(ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
mClipboardManager.addPrimaryClipChangedListener(
mOnPrimaryClipChangedListener);
}
#Override
public void onDestroy() {
super.onDestroy();
if (mClipboardManager != null) {
mClipboardManager.removePrimaryClipChangedListener(
mOnPrimaryClipChangedListener);
}
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
private boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
return false;
}
private ClipboardManager.OnPrimaryClipChangedListener mOnPrimaryClipChangedListener =
new ClipboardManager.OnPrimaryClipChangedListener() {
#Override
public void onPrimaryClipChanged() {
Log.d(TAG, "onPrimaryClipChanged");
ClipData clip = mClipboardManager.getPrimaryClip();
mThreadPool.execute(new WriteHistoryRunnable(clip.getItemAt(0).getText()));
Log.e("Copied Text","hahah"+clip.getItemAt(0).getText());
Toast.makeText(getApplicationContext(),"My App toast",Toast.LENGTH_SHORT).show();
}
};
private class WriteHistoryRunnable implements Runnable {
private final Date mNow;
private final CharSequence mTextToWrite;
public WriteHistoryRunnable(CharSequence text) {
mNow = new Date(System.currentTimeMillis());
mTextToWrite = text;
}
#Override
public void run() {
if (TextUtils.isEmpty(mTextToWrite)) {
// Don't write empty text to the file
return;
}
if (isExternalStorageWritable()) {
try {
Log.i(TAG, "Writing new clip to history:");
Log.i(TAG, mTextToWrite.toString());
BufferedWriter writer =
new BufferedWriter(new FileWriter(mHistoryFile, true));
writer.write(String.format("[%s]: ", mNow.toString()));
writer.write(mTextToWrite.toString());
writer.newLine();
writer.close();
} catch (IOException e) {
Log.w(TAG, String.format("Failed to open file %s for writing!",
mHistoryFile.getAbsoluteFile()));
}
} else {
Log.w(TAG, "External storage is not writable!");
}
}
}
}
This is used for when the app is closed or the device is restarted then it will start the service again.
BootUpRecever.java
package com.wm;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
public class BootUpReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction() == Intent.ACTION_BOOT_COMPLETED){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
//log("Starting the service in >=26 Mode from a BroadcastReceiver")
context.startForegroundService(new Intent(context, ClipboardMonitorService.class));
return;
}
//log("Starting the service in < 26 Mode from a BroadcastReceiver")
context.startService(new Intent(context, ClipboardMonitorService.class));
}
}
}
to start the activity as the app start
MainActivity.java
package com.wm;
import android.content.Intent;
import android.os.Bundle;
import com.facebook.react.ReactActivity;
public class MainActivity extends ReactActivity {
#Override
protected String getMainComponentName() {
return "wm";
}
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// TODO: Show the contents of the clipboard history.
startService(new Intent(this, ClipboardMonitorService.class));
}
}
Here are the permissions and to start the service
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.wm">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application
android:name=".MainApplication"
android:label="#string/app_name"
android:icon="#mipmap/ic_launcher"
android:roundIcon="#mipmap/ic_launcher_round"
android:allowBackup="true"
android:theme="#style/AppTheme">
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
android:launchMode="singleTask"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
<service
android:name=".ClipboardMonitorService"
android:label="Clipboard Monitor"
android:exported="false"/>
<receiver
android:name=".BootUpReceiver"
android:enabled="true"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
</application>
</manifest>

BroadcastReceiver and ACTION_BOND_STATE_CHANGED working partialy in Android 9.0

I am trying to catch the event from the pairing process with the android via Broadcast receiver. As it seems, the BluetoothDevice.BOND_BONDING is works, but the BluetoothDevice.BOND_BONDED not.
In the old android versions this worked (tried with Android 6 and 7), however with the newer ones (tried Android 9, several devices) this does not work. In order to reproduce the problem I've made a simple program:
Java file:
package com.example.bluetoothtest;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
public class MainActivity extends AppCompatActivity {
BroadcastReceiver receiver;
BluetoothDevice mDevice;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)){
mDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (mDevice.getBondState() == BluetoothDevice.BOND_BONDED) {
//means device paired
Log.d("bt", "bonded");
}
else if(mDevice.getBondState() == BluetoothDevice.BOND_BONDING) {
Log.d("bt", "bonding");
}
}
}
};
}
#Override
protected void onStart() {
super.onStart();
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
registerReceiver(receiver, filter);
}
#Override
protected void onStop() {
super.onStop();
unregisterReceiver(receiver);
}
}
Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.bluetoothtest">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
</manifest>
Did anybody else notice this problem? Am I missing a permission? Couldn't find anything relevant on the net.
You should try to retrieve the EXTRA_BOND_STATE like that :
val state = intent.extras?.get(BluetoothDevice.EXTRA_BOND_STATE) as Int
I have faced a similar problem. I have noticed one thing with devices such as HeadPhone, mouse or keyboard is that when you pair such devices, it is immediately connected to our Android device.
So android send us
android.bluetooth.device.action.ACL_CONNECTED
connected broadcast immediately. In case we receive this broadcast, it is safe to assume that Bluetooth device is already paired.
I would recommend adding this permission for Android 12 and above devices to listen to the connected broadcast.
android.permission.BLUETOOTH_CONNECT

How to receive SMS using Android service with BroadcastReceiver without GUI

I have been working on an application that use to receive SMS and show a Toast using Broadcast Receiver and i have an activity with no purpose, when i removed that activity and build the apk and run on my phone, application is not responding when SMS is received (no Toast showing), although remaining code is same as it was previously. Can anyone help please i am so stuck and couldn't help myself reading hundreds of answers. I studied i should create a service but still no Toast is appearing. below is my code. I can not have any GUI in my application even don't want to have auto kill activity.
BroadcastReceiver.java
package com.test.testservice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.widget.Toast;
public class SmsReceiver extends BroadcastReceiver {
public static final String SMS_BUNDLE = "pdus";
private static final String LOG = "SmsBroadcastReceiver";
#Override
public void onReceive(Context context, Intent intent) {
Bundle intentExtras = intent.getExtras();
if (intentExtras != null) {
Object[] sms = (Object[]) intentExtras.get(SMS_BUNDLE);
if (sms != null)
{
String smsMessageStr = "";
for (int i = 0; i < sms.length; ++i)
{
SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) sms[i]);
String smsBody = smsMessage.getMessageBody().toString();
String address = smsMessage.getOriginatingAddress();
smsMessageStr += "SMS From: " + address + "\n";
smsMessageStr += smsBody + "\n";
}
Toast.makeText(context, smsMessageStr, Toast.LENGTH_LONG).show();
//MyService objService=new MyService();
//objService.startService(intent);
//objService.stopService(intent);
Intent myIntent = new Intent(context, MyService.class);
//myIntent.putExtra("Sender", Sender);
//myIntent.putExtra("Fullsms", Fullsms);
context.startService(myIntent);
}
}
}
}
MyService.java
package com.test.testservice;
import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;
import android.widget.Toast;
public class MyService extends Service {
private static final String LOG = "MyService";
#Override
public boolean stopService(Intent name) {
if (super.stopService(name))
{
Toast.makeText(this,"HELLO stopService",Toast.LENGTH_LONG).show();
Log.i(LOG, "stopService");
return true;
}
else return false;
}
#Override
public ComponentName startService(Intent service) {
return super.startService(service);
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
Toast.makeText(this,"HELLO onCreate",Toast.LENGTH_LONG).show();
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Toast.makeText(this,"HELLO onStart",Toast.LENGTH_LONG).show();
}
}
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.test.testservice">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<receiver android:name=".SmsReceiver" android:enabled="true" android:exported="true">
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.REBOOT"/>
</intent-filter>
</receiver>
</application>
<service android:name="com.test.testservice.service.MyService"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WRITE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
</manifest>
Unless you are creating your own phone, or your own custom ROM, you need the activity. Your BroadcastReceiver will not work when your app is first installed. It will only start to work once the user has launched your activity (or something else uses an explicit Intent to start one of your components).
I can not have any GUI in my application
Then your app will not work on Android 3.1+ devices, which make up the vast majority of the Android device ecosystem.

Rejecting Incoming Calls Immediately Android

Can we block incoming phone calls in android before it reaches the phone application?
I have made an application to block incoming phone calls my problem is that even though the call is suspended immediately it pops up the calling screen for a second. Any suggestions how to avoid that inefficiency?
Also if there is a way to delete the phone call from the call history please let me know how to do it?
This is my main activity
import android.Manifest;
import android.content.pm.PackageManager;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
private static final int PERMISSION_REQUEST_PHONE_STATE_GRANTED = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getPermission();
}
private void getPermission() {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.READ_PHONE_STATE) !=
PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]
{Manifest.permission.READ_PHONE_STATE},
PERMISSION_REQUEST_PHONE_STATE_GRANTED);
}
}
}
This is my CallReceiver class which extends BroadcastReceiver
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.TelephonyManager;
import com.android.internal.telephony.ITelephony;
import java.lang.reflect.Method;
public class CallReceiver extends BroadcastReceiver {
private ITelephony telephonyService;
#Override
public void onReceive(Context context, Intent intent) {
TelephonyManager telephony = (TelephonyManager)
context.getSystemService(Context.TELEPHONY_SERVICE);
//make sure it's not an outgoing call
if (telephony.getCallState() == 1) {
try {
Class c = Class.forName(telephony.getClass().getName());
Method m = c.getDeclaredMethod("getITelephony");
m.setAccessible(true);
telephonyService = (ITelephony) m.invoke(telephony);
telephonyService.endCall();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
This is my manifest file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.shulem.phonecallsblocker">
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission
android:name="android.permission.READ_PHONE_STATE"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category
android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<receiver
android:name=".CallReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action
android:name="android.intent.action.PHONE_STATE"/>
</intent-filter>
</receiver>
</application>
</manifest>
And this is a picture of the popup screen (which pops up after the call is already suspended on the caller’s side)enter image description here
Ps
I tried to add android priority but it didn’t help.
Relying on phone state to determine if there is an incoming call and then ending it via TelephonyManager is never going to be a reliable approach to implementing a call screening app of this nature. The broadcasts for phone state are sent asynchronously while the system is busy doing all sorts of other things related to call setup. So on some devices it might work, but on others there is a good chance it won't.

network receiver is not working

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.

Categories

Resources