how to use ussdinterceptor in android - android

How to use ussdinterceptor service in android is question which is asked a lot. and the responses for it are poor.
this is my response.
first the service it self.
classes for the package com.example.ussdcodes
BootReceiver.java
package com.example.ussdcodes;
//import com.example.ussdcodes.R;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class BootReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Log.d("USSDService", context.getString(R.string.service_started));
context.startService(new Intent(context,USSDDumbExtendedNetworkService.class));
}
}
USSDDumbExtendedNetworkService.java
package com.example.ussdcodes;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.IBinder;
import android.os.PatternMatcher;
import android.os.RemoteException;
import android.util.Log;
import com.android.internal.telephony.IExtendedNetworkService;
//import com.android.internal.telephony.IExtendedNetworkService;
import com.example.ussdcodes.R;
/**
* Service implements IExtendedNetworkService interface.
* USSDDumbExtendedNetworkService
* Service must have name "com.android.ussd.IExtendedNetworkService" of the intent declared
* in the Android manifest file so com.android.phone.PhoneUtils class bind
* to this service after system rebooted.
* Please note service is loaded after system reboot!
* Your application must check is system rebooted.
* #see Util#syslogHasLine(String, String, String, boolean)
*/
public class USSDDumbExtendedNetworkService extends Service {
public static final String TAG = "CommandusUSSDExtNetSvc";
public static final String LOG_STAMP = "*USSDTestExtendedNetworkService bind successfully*";
public static final String URI_SCHEME = "ussdcodes";
public static final String URI_AUTHORITY = "android.com";
public static final String URI_PATH = "/";
public static final String URI_PAR = "return";
public static final String URI_PARON = "on";
public static final String URI_PAROFF = "off";
public static final String MAGIC_ON = ":ON;)";
public static final String MAGIC_OFF = ":OFF;(";
public static final String MAGIC_RETVAL = ":RETVAL;(";
public static final String RESULT = "result";
private static boolean mActive = true;
private static CharSequence mRetVal = null;
private Context mContext = null;
private String msgUssdRunning = "USSD running...";
final BroadcastReceiver mReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_INSERT.equals(intent.getAction())) {
mContext = context;
if (mContext != null) {
msgUssdRunning = mContext.getString(R.string.USSD_run);
mActive = true;
Log.d(TAG, "activate");
}
} else if (Intent.ACTION_DELETE.equals(intent.getAction())) {
mContext = null;
mActive = false;
Log.d(TAG, "deactivate");
}
}
};
private final IExtendedNetworkService.Stub mBinder = new IExtendedNetworkService.Stub() {
#Override
public void setMmiString(String number) throws RemoteException {
Log.d(TAG, "setMmiString: " + number);
Intent intent =new Intent("com.example.ussdcodes.setmmistring") ;
intent.putExtra("ussdCode", number);
sendBroadcast(intent);
}
#Override
public CharSequence getMmiRunningText() throws RemoteException {
Log.d(TAG, "getMmiRunningText: " + msgUssdRunning);
return msgUssdRunning;
}
#Override
public CharSequence getUserMessage(CharSequence text)
throws RemoteException {
/* if (MAGIC_ON.contentEquals(text)) {
mActive = true;
Log.d(TAG, "control: ON");
return text;
} else {
if (MAGIC_OFF.contentEquals(text)) {
mActive = false;
Log.d(TAG, "control: OFF");
return text;
} else {
if (MAGIC_RETVAL.contentEquals(text)) {
mActive = false;
Log.d(TAG, "control: return");
return mRetVal;
}
}
}
if (!mActive) {
Log.d(TAG, "getUserMessage deactivated: " + text);
return text;
} */
String s = text.toString();
// store s to the !
Uri uri = new Uri.Builder()
.scheme(URI_SCHEME)
.authority(URI_AUTHORITY)
.path(URI_PATH)
.appendQueryParameter(URI_PAR, text.toString())
.build();
// Intent intent =new Intent(Intent.ACTION_GET_CONTENT, uri) ;
// Intent intent =new Intent("com.example.ussdcodes", uri) ;
Intent intent =new Intent("com.example.ussdcodes.getusermsg") ;
intent.putExtra("result", s);
sendBroadcast(intent);
mActive = false;
mRetVal = text;
Log.d(TAG, "getUserMessage: " + text + "=" + s);
return null;
}
#Override
public void clearMmiString() throws RemoteException {
Log.d(TAG, "clearMmiString");
}
};
/**
* Put stamp to the system log when PhoneUtils bind to the service
* after Android has rebooted. Application must call {#link Util#syslogHasLine(String, String, String, boolean)} to
* check is phone rebooted or no. Without reboot phone application does not bind tom this service!
*/
#Override
public IBinder onBind(Intent intent) {
// Do not localize!
Log.i(TAG, LOG_STAMP);
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_INSERT);
filter.addAction(Intent.ACTION_DELETE);
filter.addDataScheme(URI_SCHEME);
filter.addDataAuthority(URI_AUTHORITY, null);
filter.addDataPath(URI_PATH, PatternMatcher.PATTERN_LITERAL);
registerReceiver(mReceiver, filter);
return mBinder;
}
public IBinder asBinder() {
Log.d(TAG, "asBinder");
return mBinder;
}
}
the aidl for com.android.internal.telephony
IExtendedNetworkService.aidl
package com.android.internal.telephony;
/**
* Interface used to interact with extended MMI/USSD network service.
*/
interface IExtendedNetworkService {
/**
* Set a MMI/USSD command to ExtendedNetworkService for further process.
* This should be called when a MMI command is placed from panel.
* #param number the dialed MMI/USSD number.
*/
void setMmiString(String number);
/**
* return the specific string which is used to prompt MMI/USSD is running
*/
CharSequence getMmiRunningText();
/**
* Get specific message which should be displayed on pop-up dialog.
* #param text original MMI/USSD message response from framework
* #return specific user message correspond to text. null stands for no pop-up dialog need to show.
*/
CharSequence getUserMessage(CharSequence text);
/**
* Clear pre-set MMI/USSD command.
* This should be called when user cancel a pre-dialed MMI command.
*/
void clearMmiString();
}
the manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.ussdcodes"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="21" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<receiver android:name="com.example.ussdcodes.BootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<service
android:name=".USSDDumbExtendedNetworkService" >
<intent-filter android:icon="#drawable/ic_launcher">
<action android:name="com.android.ussd.IExtendedNetworkService" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>
</application>
</manifest>
now the activity that uses the service (don't forgot to reboot the phone after installing the service)
MainActivity.java
package com.example.usingussdservice;
import android.app.Activity;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
public class MainActivity extends Activity {
UssdMsg ussdMsg = new UssdMsg();
UssdsetMmi ussdsetMmi = new UssdsetMmi();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ussdMsg.setMainActivityHandler(this);
ussdsetMmi.setMainActivityHandler(this);
// com.example.ussdcodes
IntentFilter fltr_ussdmsg = new IntentFilter("com.example.ussdcodes.getusermsg");
registerReceiver(ussdMsg,fltr_ussdmsg);
IntentFilter fltr_setmmistring = new IntentFilter("com.example.ussdcodes.setmmistring");
registerReceiver(ussdsetMmi,fltr_setmmistring);
}
public void onClick(View v) {
sendUssd( ) ;
}
public void sendUssd( )
{
//codeToSend=*600*1*#
String codeToSend ;
codeToSend = "tel:" + Uri.encode("*") + "600"+ Uri.encode("*")+"1"+ Uri.encode("#");
// codeToSend = "tel:" + codeUssd ;
startActivityForResult(new Intent("android.intent.action.CALL",
Uri.parse(codeToSend)), 1);
}
}
UssdMsg.java
package com.example.usingussdservice;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsManager;
import android.telephony.SmsMessage;
import android.util.Log;
import android.widget.Toast;
public class UssdMsg extends BroadcastReceiver {
// Get the object of SmsManager
MainActivity mainActivity = null;
void setMainActivityHandler(MainActivity mainActivity ){
this.mainActivity=mainActivity;
}
public void onReceive(Context context, Intent intent) {
setMainActivityHandler(mainActivity);
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(context,
"inside UssdMsg.onReceive", duration);
toast.show();
Bundle bundle = intent.getExtras();
if (bundle != null) {
String string = bundle.getString("result");
Toast toast2 = Toast.makeText(context,
"result="+string, duration);
toast2.show();
}
}
}
UssdsetMmi.java
package com.example.usingussdservice;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsManager;
import android.telephony.SmsMessage;
import android.util.Log;
import android.widget.Toast;
public class UssdsetMmi extends BroadcastReceiver {
// Get the object of SmsManager
MainActivity mainActivity = null;
void setMainActivityHandler(MainActivity mainActivity ){
this.mainActivity=mainActivity;
}
final SmsManager sms = SmsManager.getDefault();
public void onReceive(Context context, Intent intent) {
setMainActivityHandler(mainActivity);
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(context,
"inside UssdsetMmi.onReceive", duration);
toast.show();
Bundle bundle = intent.getExtras();
if (bundle != null) {
String string = bundle.getString("ussdCode");
Toast toast2 = Toast.makeText(context,
"ussdCode="+string, duration);
toast2.show();
}
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.usingussdservice"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="21" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.CALL_PHONE"/>
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="${relativePackage}.${activityClass}" >
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_marginLeft="35dp"
android:layout_marginTop="34dp"
android:onClick="onClick"
android:text="send ussd code" />
</RelativeLayout>

Related

Sending notifications from smartphone to Wear OS smartwatch

I've been trying to develop a simple app that can send notifications from a smartphone to an Wear OS smartwatch (more specifically, a Huawei Smartwatch 2).
I've used this code as a basis: github link. Note that this code doens't have the "notifications part" I'm trying to develop.
The bottom line is: I can receive data on the smartwatch, but only when the app on it is running. The ServiceListener service, from what I could tell, from debugging, is not being activated. Basically, anything I write on that file, even Log data, isn't being displayed.
The ServiceListener service:
package com.example.nowor_000.sincronizaciondatos;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationManagerCompat;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.wearable.DataApi;
import com.google.android.gms.wearable.DataEvent;
import com.google.android.gms.wearable.DataEventBuffer;
import com.google.android.gms.wearable.DataMapItem;
import com.google.android.gms.wearable.MessageEvent;
import com.google.android.gms.wearable.Wearable;
import com.google.android.gms.wearable.WearableListenerService;
import static android.content.ContentValues.TAG;
import static com.google.android.gms.wearable.PutDataRequest.WEAR_URI_SCHEME;
/**
* Created by nowor_000 on 26/11/2015.
*/
public class ServiceListener extends WearableListenerService {
public static final String NOTIFICATION_PATH = "/notification";
public static final String NOTIFICATION_TIMESTAMP = "timestamp";
public static final String NOTIFICATION_TITLE = "title";
public static final String NOTIFICATION_CONTENT = "content";
public static final String ACTION_DISMISS = "com.example.nowor_000.sincronizaciondatos.DISMISS";
//private static final String WEAR_INICIAR_ACTIVIDAD = "/iniciar";
private static final String START_ACTIVITY_PATH = "/start-activity";
private int notificationId = 001;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "onStartCommand ServiceListener.");
if (null != intent) {
String action = intent.getAction();
if (ACTION_DISMISS.equals(action)) {
dismissNotification();
}
}
return super.onStartCommand(intent, flags, startId);
}
#Override
public void onDataChanged(DataEventBuffer dataEvents) {
Log.i(TAG, "onDataChanged ServiceListener.");
for (DataEvent dataEvent : dataEvents) {
if (dataEvent.getType() == DataEvent.TYPE_CHANGED) {
if (NOTIFICATION_PATH.equals(dataEvent.getDataItem().getUri().getPath())) {
DataMapItem dataMapItem = DataMapItem.fromDataItem(dataEvent.getDataItem());
String title = dataMapItem.getDataMap().getString(NOTIFICATION_TITLE);
String content = dataMapItem.getDataMap().getString(NOTIFICATION_CONTENT);
sendNotification(title, content);
}
}
}
}
private void sendNotification(String title, String content) {
Log.i(TAG, "Sending notification.");
// this intent will open the activity when the user taps the "open" action on the notification
Intent viewIntent = new Intent(this, MainActivity.class);
PendingIntent pendingViewIntent = PendingIntent.getActivity(this, 0, viewIntent, 0);
// this intent will be sent when the user swipes the notification to dismiss it
Intent dismissIntent = new Intent(ACTION_DISMISS);
PendingIntent pendingDeleteIntent = PendingIntent.getService(this, 0, dismissIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher)
.setContentTitle(title)
.setContentText(content)
.setDeleteIntent(pendingDeleteIntent)
.setContentIntent(pendingViewIntent);
Notification notification = builder.build();
NotificationManagerCompat notificationManagerCompat = NotificationManagerCompat.from(this);
notificationManagerCompat.notify(notificationId++, notification);
}
private void dismissNotification() {
new ServiceListener.DismissNotificationCommand(this).execute();
}
private class DismissNotificationCommand implements GoogleApiClient.ConnectionCallbacks, ResultCallback<DataApi.DeleteDataItemsResult>, GoogleApiClient.OnConnectionFailedListener {
private static final String TAG = "DismissNotification";
private final GoogleApiClient mGoogleApiClient;
public DismissNotificationCommand(Context context) {
mGoogleApiClient = new GoogleApiClient.Builder(context)
.addApi(Wearable.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
public void execute() {
mGoogleApiClient.connect();
}
#Override
public void onConnected(Bundle bundle) {
final Uri dataItemUri =
new Uri.Builder().scheme(WEAR_URI_SCHEME).path(NOTIFICATION_PATH).build();
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Deleting Uri: " + dataItemUri.toString());
}
Wearable.DataApi.deleteDataItems(
mGoogleApiClient, dataItemUri).setResultCallback(this);
}
#Override
public void onConnectionSuspended(int i) {
Log.d(TAG, "onConnectionSuspended");
}
#Override
public void onResult(DataApi.DeleteDataItemsResult deleteDataItemsResult) {
if (!deleteDataItemsResult.getStatus().isSuccess()) {
Log.e(TAG, "dismissWearableNotification(): failed to delete DataItem");
}
mGoogleApiClient.disconnect();
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.d(TAG, "onConnectionFailed");
}
}
}
The MainActivity on the smartphone:
package com.example.nowor_000.sincronizaciondatos;
import android.os.Bundle;
import android.provider.SyncStateContract;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.wearable.DataApi;
import com.google.android.gms.wearable.MessageApi;
import com.google.android.gms.wearable.Node;
import com.google.android.gms.wearable.NodeApi;
import com.google.android.gms.wearable.PutDataMapRequest;
import com.google.android.gms.wearable.PutDataRequest;
import com.google.android.gms.wearable.Wearable;
import static android.content.ContentValues.TAG;
public class MainActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, View.OnClickListener {
public static final String NOTIFICATION_PATH = "/notification";
public static final String NOTIFICATION_TIMESTAMP = "timestamp";
public static final String NOTIFICATION_TITLE = "title";
public static final String NOTIFICATION_CONTENT = "content";
public static final String ACTION_DISMISS = "de.peterfriese.notificationwithopenactivityonwearableaction.DISMISS";
/**
* sincronizacion
*/
private static final String KEY_CONTADOR = "com.example.key.contador";
private static final String ITEM_CONTADOR = "/contador";
/**
* sincronizacion
*/
private static final String WEAR_INICIAR_ACTIVIDAD = "/iniciar";
private static final String WEAR_ENVIAR_TEXTO = "/enviar_texto";
Button btnEnviarTexto;
EditText editText;
private int contador;
/**
* CLIENTE
*/
private GoogleApiClient apiClient;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
/**
*API CLIENT es clave para establecer la comunicaciĆ³n
*/
apiClient = new GoogleApiClient.Builder(this)
.addApi(Wearable.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
addViews();
/**
* sincronizacion
*/
final TextView textoContador = (TextView) findViewById(R.id.textoContador);
textoContador.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
contador++;
textoContador.setText(Integer.toString(contador));
PutDataMapRequest putDataMapReq = PutDataMapRequest.create(ITEM_CONTADOR);
putDataMapReq.getDataMap().putInt(KEY_CONTADOR, contador);
PutDataRequest putDataReq = putDataMapReq.asPutDataRequest();
PendingResult<DataApi.DataItemResult> resultado = Wearable.DataApi.putDataItem(apiClient, putDataReq);
/**
* ESTA LINEA SE ME OLVIDO EN EL VIDEOTUTORIAL
*/
enviarMensaje(ITEM_CONTADOR, Integer.toString(contador));
}
});
/**
* sincronizacion
*/
}
private void addViews() {
editText = (EditText) findViewById(R.id.edtitText);
btnEnviarTexto = (Button) findViewById(R.id.btnEnviarTexto);
btnEnviarTexto.setOnClickListener(this);
}
#Override
public void onClick(View v) {
sendNotification();
switch (v.getId()) {
case R.id.btnEnviarTexto:
String text = editText.getText().toString();
if (!TextUtils.isEmpty(text)) {
enviarMensaje(WEAR_ENVIAR_TEXTO, text);
editText.getText().clear();
editText.requestFocus();
} else {
enviarMensaje(WEAR_ENVIAR_TEXTO, "\n->Escribe un mensaje, en el EditText<-");
}
break;
}
}
//<editor-fold desc="ENVIAR MENSAJE EditText">
private void enviarMensaje(final String path, final String texto) {
new Thread(new Runnable() {
#Override
public void run() {
NodeApi.GetConnectedNodesResult nodos = Wearable.NodeApi.getConnectedNodes(apiClient).await();
for (Node nodo : nodos.getNodes()) {
Wearable.MessageApi.sendMessage(apiClient, nodo.getId(), path, texto.getBytes())
.setResultCallback(
new ResultCallback<MessageApi.SendMessageResult>() {
#Override
public void onResult(MessageApi.SendMessageResult resultado) {
if (!resultado.getStatus().isSuccess()) {
Log.e("sincronizacion", "Error al enviar mensaje. Codigo" + resultado.getStatus().getStatusCode());
}
}
}
);
}
}
}).start();
}
//</editor-fold>
//<editor-fold desc="CICLO DE VIDA">
#Override
protected void onStart() {
super.onStart();
apiClient.connect();
}
#Override
protected void onStop() {
if (apiClient != null && apiClient.isConnected()) {
apiClient.disconnect();
}
super.onStop();
}
//</editor-fold>
//<editor-fold desc="METODOS API DATA LAYER">
#Override
public void onConnected(Bundle bundle) {
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
//</editor-fold>
//<editor-fold desc="MENU">
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
//</editor-fold>
private void sendNotification() {
if (apiClient.isConnected()) {
Log.i(TAG, "Sending data.");
PutDataMapRequest dataMapRequest = PutDataMapRequest.create(NOTIFICATION_PATH);
// Make sure the data item is unique. Usually, this will not be required, as the payload
// (in this case the title and the content of the notification) will be different for almost all
// situations. However, in this example, the text and the content are always the same, so we need
// to disambiguate the data item by adding a field that contains teh current time in milliseconds.
dataMapRequest.getDataMap().putDouble(NOTIFICATION_TIMESTAMP, System.currentTimeMillis());
dataMapRequest.getDataMap().putString(NOTIFICATION_TITLE, "This is the title");
dataMapRequest.getDataMap().putString(NOTIFICATION_CONTENT, "This is a notification with some text.");
PutDataRequest putDataRequest = dataMapRequest.asPutDataRequest().setUrgent();
Wearable.DataApi.putDataItem(apiClient, putDataRequest);
} else {
Log.e(TAG, "No connection to wearable available!");
}
}
}
The AndroidManifest for the smartphone:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.nowor_000.sincronizaciondatos">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<!--ETIQUETA PPARA INDICAR LA VERSION DE GOOGLE PLAY QUE ESTAMOS USANDO -->
<meta-data android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
<activity
android:name=".MainActivity"
android:label="#string/app_name"
android:theme="#style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
The AndroidManifest for the smartwatch:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.nowor_000.sincronizaciondatos">
<uses-feature android:name="android.hardware.type.watch" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#android:style/Theme.DeviceDefault">
<meta-data android:name="com.google.android.gms.version" android:value="#integer/google_play_services_version" />
<uses-library android:name="com.google.android.wearable"
android:required="true" />
<activity
android:name=".MainActivity"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".ServiceListener"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.google.android.gms.wearable.DATA_CHANGED" />
<action android:name="com.google.android.gms.wearable.MESSAGE_RECEIVED" />
<data android:scheme="wear" android:host="*"
android:path="/start-activity" />
</intent-filter>
</service>
</application>
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE" />
</manifest>
If you need any more code please say. Thanks!

How to start something when voice call starts?

I have built full voice recorder application.
I would like to start recording when a voice call starts on the phone, how can I detect the Calls state? tried some code and it didn't work for me.
I just need to know hot to start recording when a voice call starts (incoming and outgoing).
Here is an example of what you need.
Declare receiver in AndroidManifest
<receiver android:name=".IncomingCall">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
Give read phone state permission in AndroidManifest
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
Create a class IncomingCall with extends BroadcastReceiver class
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.widget.Toast;
/**
* Created by matheszabi on Aug/20/2017 0020.
*/
public class IncomingCall extends BroadcastReceiver {
private Context context;
public void onReceive(Context context, Intent intent) {
this.context = context;
try {
// TELEPHONY MANAGER class object to register one listner
TelephonyManager tmgr = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
//Create Listner
MyPhoneStateListener PhoneListener = new MyPhoneStateListener();
// Register listener for LISTEN_CALL_STATE
tmgr.listen(PhoneListener, PhoneStateListener.LISTEN_CALL_STATE);
} catch (Exception e) {
Log.e("Phone Receive Error", " " + e);
}
}
private class MyPhoneStateListener extends PhoneStateListener {
public void onCallStateChanged(int state, String incomingNumber) {
Log.d("MyPhoneListener",state+" incoming no:"+incomingNumber);
if (state == 1) {
String msg = "New Phone Call Event. Incomming Number : "+incomingNumber;
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(context, msg, duration);
toast.show();
}
}
}
}
Above Android 6.0 you need to handle a bit different the permissions:
import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private static final int MY_REQUEST_CODE = 1234;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
protected void onResume() {
super.onResume();
if (checkSelfPermission(Manifest.permission.READ_PHONE_STATE)
!= PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.READ_PHONE_STATE},
MY_REQUEST_CODE);
}
}
public void onRequestPermissionResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == MY_REQUEST_CODE) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// Now user should be able to use camera
Toast.makeText(this, "I have access", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "I DON'T have access", Toast.LENGTH_SHORT).show();
}
}
}
}
You must allow the permissions at the first time run:
Here is the screenshot of the working code:
I found how to do so:
package com.example.tsuryohananov.mycallrecorder;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.widget.Toast;
/**
* Created by tsuryohananov on 20/08/2017.
*/
public class MyPhoneReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Bundle extras = intent.getExtras();
if (extras != null) {
String state = extras.getString(TelephonyManager.EXTRA_STATE);
Log.d("MY_DEBUG_TAG", state);
if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
String phoneNumber = extras.getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
Log.d("MY_DEBUG_TAG", phoneNumber);
// here i need to save the number for the listview.
}
if ((state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK))){
String phoneNumber = extras.getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
Toast.makeText(context,"Answered" + phoneNumber, Toast.LENGTH_SHORT).show();
MainActivity.recordStart();
}
if (state.equals(TelephonyManager.EXTRA_STATE_IDLE)){
Toast.makeText(context,"Idle State", Toast.LENGTH_SHORT).show();
MainActivity.stopRecord();
}
}
}
}

android ActivityRecognition not calling onHandleIntent

I have put together this piece of code to get the users activity, to see is he walking or driving or still, but its not working, onHandleIntent never called. it is connecting to GoogleApiClient.
Here is my code
Activity Layout
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin" tools:context=".MainActivity">
<TextView android:text="#string/hello_world" android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/msg" />
MainActivity
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.ActivityRecognition;
public class MainActivity extends ActionBarActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
private Context mContext;
private GoogleApiClient mGApiClient;
private BroadcastReceiver receiver;
private TextView textView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//get the textview
textView = (TextView) findViewById(R.id.msg);
//Set the context
mContext = this;
//Check Google Play Service Available
if(isPlayServiceAvailable()) {
mGApiClient = new GoogleApiClient.Builder(this)
.addApi(ActivityRecognition.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
//Connect to gPlay
mGApiClient.connect();
}else{
Toast.makeText(mContext, "Google Play Service not Available", Toast.LENGTH_LONG).show();
}
//Broadcast receiver
receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String v = "Activity :" +
intent.getStringExtra("act") + " " +
"Confidence : " + intent.getExtras().getInt("confidence") + "n";
v += textView.getText();
textView.setText(v);
}
};
IntentFilter filter = new IntentFilter();
filter.addAction("SAVVY");
registerReceiver(receiver, filter);
}
private boolean isPlayServiceAvailable() {
return GooglePlayServicesUtil.isGooglePlayServicesAvailable(mContext) == ConnectionResult.SUCCESS;
}
#Override
public void onConnected(Bundle bundle) {
Intent i = new Intent(this, ActivityRecognitionIntentService.class);
PendingIntent mActivityRecongPendingIntent = PendingIntent.getService(this, 0, i, PendingIntent.FLAG_UPDATE_CURRENT);
Log.d("Saquib", "connected to ActRecog " + "PI " +mActivityRecongPendingIntent.toString() );
ActivityRecognition.ActivityRecognitionApi.requestActivityUpdates(mGApiClient, 0, mActivityRecongPendingIntent);
}
#Override
public void onConnectionSuspended(int i) {
Log.d("Saquib", "suspended to ActRecog");
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
Log.d("Saquib", "Not connected to ActRecog");
}
#Override
protected void onDestroy() {
super.onDestroy();
mGApiClient.disconnect();
unregisterReceiver(receiver);
}
}
ActivityRecognitionIntentService
import android.app.IntentService;
import android.content.Intent;
import android.util.Log;
import com.google.android.gms.location.ActivityRecognitionResult;
import com.google.android.gms.location.DetectedActivity;
/**
* Created by tutsberry on 17/03/15.
*/
public class ActivityRecognitionIntentService extends IntentService {
public ActivityRecognitionIntentService() {
super("ActivityRecognitionIntentService");
}
#Override
protected void onHandleIntent(Intent intent) {
if(ActivityRecognitionResult.hasResult(intent)) {
ActivityRecognitionResult result = ActivityRecognitionResult.extractResult(intent);
DetectedActivity detectedActivity = result.getMostProbableActivity();
int confidence = detectedActivity.getConfidence();
String mostProbableName = getActivityName(detectedActivity.getType());
Intent i = new Intent("SAVVY");
i.putExtra("act", mostProbableName);
i.putExtra("confidence", confidence);
Log.d("Saquib", "mostProbableName " + mostProbableName);
Log.d("Saquib", "Confidence : " + confidence);
//Send Broadcast
this.sendBroadcast(i);
}else {
Log.d("Saquib", "Intent had no data returned");
}
}
private String getActivityName(int type) {
switch (type)
{
case DetectedActivity.IN_VEHICLE:
return "in_vehicle";
case DetectedActivity.ON_BICYCLE:
return "on_bicycle";
case DetectedActivity.WALKING:
return "walking";
case DetectedActivity.STILL:
return "still";
case DetectedActivity.TILTING:
return "tilting";
case DetectedActivity.UNKNOWN:
return "unknown";
case DetectedActivity.RUNNING:
return "running";
}
return "n/a";
}
}
and manifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.tutsberry.moveyours" >
<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION"/>
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".ActivityRecognitionIntentService">
</service>
</application>
</manifest>
Guys please help, google doc is no use for ActivityRecognition
Maybe you are missing the
<uses-permission android:name="android.permission.INTERNET" />
Make sure that you are connected to the internet beforehand. I think otherwise it will not work. The first time you connect to google play services you must be connected to the internet.

Android: IncomingCallInterceptor TelephonyManager.EXTRA_STATE Toast and Vibration

I would like to bring up a Toast and vibrate when call status is Idle.
I added this in the manifest file:
<receiver android:name="IncomingCallInterceptor">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE"/>
</intent-filter>
</receiver>
And this is IncomingCallInterceptor
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Vibrator;
import android.telephony.TelephonyManager;
import android.widget.Toast;
import android.app.Activity;
public class IncomingCallInterceptor extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent)
{
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
String msg = "Phone state changed to " + state;
if (TelephonyManager.EXTRA_STATE_RINGING.equals(state))
{
String incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
msg += ". Incoming number is " + incomingNumber;
}
Toast.makeText(context, msg, Toast.LENGTH_LONG).show();
if(msg == "IDLE")
{
ok() ;
}
}
public void ok()
{
Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
v.vibrate(3000);
}
}
}
And I received this error:
Description Resource Path Location Type
The method getSystemService(String) is undefined for the type IncomingCallInterceptor IncomingCallInterceptor.java line 39 Java Problem
Make Sure You Have Added VIBRATE permission in manifest as:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="...">
<uses-permission android:name="android.permission.VIBRATE"/>
<application android:label="...">
...
</application>
</manifest>
change Your Code as:
public class IncomingCallInterceptor extends BroadcastReceiver {
private Context contextc;
#Override
public void onReceive(Context context, Intent intent)
{
this.contextc=context;
//YOUR CODE HERE
public void ok()
{
Vibrator v = (Vibrator)contextc.getSystemService(Context.VIBRATOR_SERVICE);
v.vibrate(3000);
}

Android volatile not working?

I have an Activity class, in which I have a static flag, let's say
public static volatile flag = false;
Then in the class, I start a thread, which checks the flag and do different things.
I also have a broadcastreceiver, which sets the flag to true or false.
I though volatile will force the flag to the most recent value. But I can see my broadcastreceiver sets the static flag to true, but my thread is still getting it as false.
Am I missing something basic here? Any help would be appreciated!
Simplified Code (Updated) - So the flag is supposed to change to true after one minute. But it never did. But message from broadcast receiver shows it has been change to true
TestappActivity.java:
package com.test;
import java.util.Calendar;
import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Bundle;
public class TestappActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Intent intent0 = new Intent(this, TestService.class);
this.startService(intent0);
Intent intent = new Intent(this, TestReceiver.class);
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
PendingIntent sender = PendingIntent.getBroadcast(this,
1, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
Calendar slot = Calendar.getInstance();
int min = slot.get(Calendar.MINUTE);
slot.set(Calendar.MINUTE, min+1);
am.set(AlarmManager.RTC_WAKEUP, slot.getTimeInMillis(), sender);
}
}
TestService.java:
package com.test;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
public class TestService extends Service {
private static final String TAG = "TestService";
public static volatile boolean flag = false;
private MyTopThread mTopThread;
public TestService() {
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
}
#Override
public void onDestroy() {
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
protect();
// We want this service to continue running until it is explicitly
// stopped, so return sticky.
return START_STICKY;
}
/**
* Run protection
*
*/
private void protect() {
mTopThread = new MyTopThread();
mTopThread.start();
}
private class MyTopThread extends Thread {
#Override
public void run() {
while (true) {
try {
Thread.sleep(150);
Log.d(TAG, "Flag is " + TestService.flag);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
TestReceiver.java:
package com.test;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class TestReceiver extends BroadcastReceiver {
final static private String TAG = "TestReceiver";
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "onReceive is triggered ...");
TestService.flag = true;
Log.d(TAG, "flag is changed to " + TestService.flag);
}
}
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.test"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="8" />
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<activity
android:name=".TestappActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".TestService" />
<receiver
android:name=".TestReceiver"
android:process=":remote" >
</receiver>
</application>
</manifest>
I think the problem is that you are running the receiver in its own process. From the docs for the android:process attribute of <receiver>:
If the name assigned to this attribute begins with a colon (':'), a new process, private to the application, is created when it's needed and the broadcast receiver runs in that process.
I think the receiver is modifying a process-local version of TestService.flag, not the one being used by TestService. Try removing the android:process attribute from the <receiver> tag in your manifest.
From this link
http://www.javamex.com/tutorials/synchronization_volatile.shtml
Essentially, volatile is used to indicate that a variable's value will
be modified by different threads.
I really hope your service thread is not this one (I don't see any other one):
private class MyTopThread extends Thread {
#Override
public void run() {
while (true) {
try {
Thread.sleep(150);
Log.d(TAG, "Flag is " + TestService.flag);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Because you have while(true) here, not while(!flag) as it should be.

Categories

Resources