I finished every configuration and tested on multiple Android devices, everything works fine, but when I test the streaming with the Vuzix M300, which is a smart glass run on Android 6, the streaming didn't happen and not even getting any error in Android Studio.Kindly help me out I am new in Vuzix m300.
Below is the java code:
package fr.pchab.androidrtc;
import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Point;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.view.Window;
import android.view.WindowManager.LayoutParams;
import android.widget.Toast;
import org.json.JSONException;
import org.webrtc.MediaStream;
import org.webrtc.VideoRenderer;
import org.webrtc.VideoRendererGui;
import fr.pchab.webrtcclient.WebRtcClient;
import fr.pchab.webrtcclient.PeerConnectionParameters;
import java.util.List;
import static android.Manifest.permission.MODIFY_AUDIO_SETTINGS;
import static android.Manifest.permission.RECORD_AUDIO;
import static android.Manifest.permission.WAKE_LOCK;
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
import static android.Manifest.permission.CAMERA;
public class RtcActivity extends Activity implements WebRtcClient.RtcListener {
private static final int PERMISSION_REQUEST_CODE = 0;
private final static int VIDEO_CALL_SENT = 666;
private static final String VIDEO_CODEC_VP9 = "VP9";
private static final String AUDIO_CODEC_OPUS = "opus";
// Local preview screen position before call is connected.
private static final int LOCAL_X_CONNECTING = 0;
private static final int LOCAL_Y_CONNECTING = 0;
private static final int LOCAL_WIDTH_CONNECTING = 100;
private static final int LOCAL_HEIGHT_CONNECTING = 100;
// Local preview screen position after call is connected.
private static final int LOCAL_X_CONNECTED = 72;
private static final int LOCAL_Y_CONNECTED = 72;
private static final int LOCAL_WIDTH_CONNECTED = 25;
private static final int LOCAL_HEIGHT_CONNECTED = 25;
// Remote video screen position
private static final int REMOTE_X = 0;
private static final int REMOTE_Y = 0;
private static final int REMOTE_WIDTH = 100;
private static final int REMOTE_HEIGHT = 100;
private VideoRendererGui.ScalingType scalingType = VideoRendererGui.ScalingType.SCALE_ASPECT_FILL;
private GLSurfaceView vsv;
private VideoRenderer.Callbacks localRender;
private VideoRenderer.Callbacks remoteRender;
private WebRtcClient client;
private String mSocketAddress;
private String callerId;
#Override
public void onCreate(Bundle savedInstanceState) {
try {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().addFlags(
LayoutParams.FLAG_FULLSCREEN
| LayoutParams.FLAG_KEEP_SCREEN_ON
| LayoutParams.FLAG_DISMISS_KEYGUARD
| LayoutParams.FLAG_SHOW_WHEN_LOCKED
| LayoutParams.FLAG_TURN_SCREEN_ON);
setContentView(R.layout.main);
requestPermission();
mSocketAddress = "http://" + getResources().getString(R.string.host);
mSocketAddress += (":" + getResources().getString(R.string.port) + "/");
vsv = (GLSurfaceView) findViewById(R.id.glview_call);
vsv.setPreserveEGLContextOnPause(true);
vsv.setKeepScreenOn(true);
VideoRendererGui.setView(vsv, new Runnable() {
#Override
public void run() {
init();
}
});
// local and remote render
remoteRender = VideoRendererGui.create(
REMOTE_X, REMOTE_Y,
REMOTE_WIDTH, REMOTE_HEIGHT, scalingType, false);
localRender = VideoRendererGui.create(
LOCAL_X_CONNECTING, LOCAL_Y_CONNECTING,
LOCAL_WIDTH_CONNECTING, LOCAL_HEIGHT_CONNECTING, scalingType, true);
final Intent intent = getIntent();
final String action = intent.getAction();
if (Intent.ACTION_VIEW.equals(action)) {
final List<String> segments = intent.getData().getPathSegments();
callerId = segments.get(0);
}
}catch (Exception e){
System.out.print("error in opening activity"+e);
}
}
private void init() {
Point displaySize = new Point();
getWindowManager().getDefaultDisplay().getSize(displaySize);
PeerConnectionParameters params = new PeerConnectionParameters(
true, false, displaySize.x, displaySize.y, 30, 1, VIDEO_CODEC_VP9, true, 1, AUDIO_CODEC_OPUS, true);
client = new WebRtcClient(this, mSocketAddress, params, VideoRendererGui.getEGLContext());
}
#Override
public void onPause() {
super.onPause();
vsv.onPause();
if(client != null) {
client.onPause();
}
}
#Override
public void onResume() {
super.onResume();
vsv.onResume();
if(client != null) {
client.onResume();
}
}
#Override
public void onDestroy() {
if(client != null) {
client.onDestroy();
}
super.onDestroy();
}
#Override
public void onCallReady(String callId) {
if (callerId != null) {
try {
answer(callerId);
} catch (JSONException e) {
e.printStackTrace();
}
} else {
//call(callId);
startCam();
}
}
public void answer(String callerId) throws JSONException {
client.sendMessage(callerId, "init", null);
startCam();
}
public void call(String callId) {
Intent msg = new Intent(Intent.ACTION_SEND);
msg.putExtra(Intent.EXTRA_TEXT, mSocketAddress + callId);
msg.setType("text/plain");
startActivityForResult(Intent.createChooser(msg, "Call someone :"), VIDEO_CALL_SENT);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == VIDEO_CALL_SENT) {
startCam();
}
}
public void startCam() {
// Camera settings
client.start("android_test");
}
#Override
public void onStatusChanged(final String newStatus) {
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), newStatus, Toast.LENGTH_SHORT).show();
}
});
}
#Override
public void onLocalStream(MediaStream localStream) {
localStream.videoTracks.get(0).addRenderer(new VideoRenderer(localRender));
VideoRendererGui.update(localRender,
LOCAL_X_CONNECTING, LOCAL_Y_CONNECTING,
LOCAL_WIDTH_CONNECTING, LOCAL_HEIGHT_CONNECTING,
scalingType);
}
#Override
public void onAddRemoteStream(MediaStream remoteStream, int endPoint) {
remoteStream.videoTracks.get(0).addRenderer(new VideoRenderer(remoteRender));
VideoRendererGui.update(remoteRender,
REMOTE_X, REMOTE_Y,
REMOTE_WIDTH, REMOTE_HEIGHT, scalingType);
VideoRendererGui.update(localRender,
LOCAL_X_CONNECTED, LOCAL_Y_CONNECTED,
LOCAL_WIDTH_CONNECTED, LOCAL_HEIGHT_CONNECTED,
scalingType);
}
#Override
public void onRemoveRemoteStream(int endPoint) {
VideoRendererGui.update(localRender,
LOCAL_X_CONNECTING, LOCAL_Y_CONNECTING,
LOCAL_WIDTH_CONNECTING, LOCAL_HEIGHT_CONNECTING,
scalingType);
}
private boolean checkPermission() {
int result = ContextCompat.checkSelfPermission(getApplicationContext(), MODIFY_AUDIO_SETTINGS);
int result1 = ContextCompat.checkSelfPermission(getApplicationContext(), CAMERA);
int result2 = ContextCompat.checkSelfPermission(getApplicationContext(), RECORD_AUDIO);
int result3 = ContextCompat.checkSelfPermission(getApplicationContext(), WRITE_EXTERNAL_STORAGE);
int result4 = ContextCompat.checkSelfPermission(getApplicationContext(), WAKE_LOCK);
return result == PackageManager.PERMISSION_GRANTED && result1 == PackageManager.PERMISSION_GRANTED && result2 == PackageManager.PERMISSION_GRANTED;
}
private void requestPermission() {
ActivityCompat.requestPermissions(this, new String[]{MODIFY_AUDIO_SETTINGS, CAMERA,RECORD_AUDIO,WRITE_EXTERNAL_STORAGE,WAKE_LOCK}, PERMISSION_REQUEST_CODE);
}
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_CODE:
if (grantResults.length > 0) {
boolean locationAccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
boolean cameraAccepted = grantResults[1] == PackageManager.PERMISSION_GRANTED;
if (locationAccepted && cameraAccepted) {
//Snackbar.make(view, "Permission Granted, Now you can access location data and camera.", Snackbar.LENGTH_LONG).show();
}
else {
//Snackbar.make(view, "Permission Denied, You cannot access location data and camera.", Snackbar.LENGTH_LONG).show();
/*if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (shouldShowRequestPermissionRationale(ACCESS_FINE_LOCATION)) {
showMessageOKCancel("You need to allow access to both the permissions",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[]{ACCESS_FINE_LOCATION, CAMERA},
PERMISSION_REQUEST_CODE);
}
}
});
return;
}
}*/
}
}
break;
}
}
}
we have just fixed a similar problem.
you may try by adjusting the bolded number parameter a little bit lower.
PeerConnectionParameters params = new PeerConnectionParameters(
true, false, displaySize.x, displaySize.y, **30**, 1, VIDEO_CODEC_VP9, true, 1, AUDIO_CODEC_OPUS, true);
At least, this helps our case.. Hope work out for you too.
Related
I added achievements to my Google Play game following Google's tutorial. They unlock fine and if I display achievements in-game immediately they show up. If I quit the game and go to the Google Game's app they don't show up and they disappear from in-game also. Any ideas? I've tried multiple accounts. Thanks!
package com.b1stable.tth;
import java.io.File;
import java.io.FileFilter;
import java.util.Locale;
import java.nio.file.Path;
import java.nio.file.PathMatcher;
import java.nio.file.FileSystems;
import java.util.Vector;
import android.os.Bundle;
import android.os.Build;
import android.content.Context;
import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.Color;
import android.net.Uri;
import android.os.Vibrator;
import android.os.VibrationEffect;
import android.util.Log;
import android.view.Surface;
import android.view.Gravity;
import org.libsdl.app.SDLActivity;
import com.b1stable.tth.License_Viewer_Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import com.google.android.gms.auth.api.signin.GoogleSignIn;
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.android.gms.auth.api.signin.GoogleSignInClient;
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
import com.google.android.gms.auth.api.signin.GoogleSignInResult;
import com.google.android.gms.auth.api.Auth;
import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.games.AchievementsClient;
import com.google.android.gms.games.AnnotatedData;
import com.google.android.gms.games.EventsClient;
import com.google.android.gms.games.Games;
import com.google.android.gms.games.GamesClient;
import com.google.android.gms.games.LeaderboardsClient;
import com.google.android.gms.games.Player;
import com.google.android.gms.games.PlayersClient;
import com.google.android.gms.games.event.Event;
import com.google.android.gms.games.event.EventBuffer;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.android.gms.tasks.Task.*;
public class TTH_Activity extends SDLActivity
{
final static int LICENSE_REQUEST = 1;
native static void resume_after_showing_license();
native static void resume_after_showing_achievements();
native static void pause();
native static void resume();
// Client used to sign in with Google APIs
private GoogleSignInClient mGoogleSignInClient;
private AchievementsClient mAchievementsClient = null;
private boolean signin_failed = false;
// request codes we use when invoking an external activity
private static final int RC_UNUSED = 5001;
private static final int RC_SIGN_IN = 9001;
// This is so the screen is never cleared pure black, only shim::black (r:35, g:30, b:60)
static boolean paused = false;
private static final String TAG = "TTH";
#Override
public void onCreate(Bundle savedInstance)
{
super.onCreate(savedInstance);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == LICENSE_REQUEST) {
if (data != null) {
if (resultCode == RESULT_OK && data.getExtras().getString("MESSAGE").equals("OK")) {
show_license_result = 0;
}
else if (resultCode == RESULT_CANCELED && data.getExtras().getString("MESSAGE").equals("FAIL")) {
show_license_result = 1;
}
else {
show_license_result = 1;
}
}
else {
show_license_result = 1;
}
resume_after_showing_license();
}
if (requestCode == RC_SIGN_IN) {
GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
if (result.isSuccess()) {
// The signed in account is stored in the result.
GoogleSignInAccount signedInAccount = result.getSignInAccount();
onConnected(signedInAccount);
}
else {
String message = result.getStatus().getStatusMessage();
if (message == null || message.isEmpty()) {
message = "An error occurred!";
}
new AlertDialog.Builder(this).setMessage(message).setNeutralButton(android.R.string.ok, null).show();
onDisconnected();
}
}
}
public void onStart() {
super.onStart();
}
#Override
public void onStop()
{
super.onStop();
pause();
}
#Override
public void onRestart()
{
super.onRestart();
resume();
}
#Override
public void onResume()
{
super.onResume();
signInSilently();
}
#Override
public void onPause()
{
super.onPause();
mAchievementsClient = null;
}
#Override
public void onPostResume()
{
super.onPostResume();
paused = true;
}
public void logString(String s)
{
Log.d("TTH", s);
}
public String getAppdataDir()
{
return getFilesDir().getAbsolutePath();
}
public String getSDCardDir()
{
File f = getExternalFilesDir(null);
if (f != null) {
return f.getAbsolutePath();
}
else {
return getFilesDir().getAbsolutePath();
}
}
static int show_license_result;
public void showLicense()
{
show_license_result = -1;
Intent intent = new Intent(this, License_Viewer_Activity.class);
startActivityForResult(intent, LICENSE_REQUEST);
}
public int getShowLicenseResult()
{
return show_license_result;
}
/*
public void openURL(String url)
{
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(intent);
}
*/
public void rumble(int milliseconds)
{
Vibrator v = (Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
if (v != null && v.hasVibrator()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
v.vibrate(VibrationEffect.createOneShot(milliseconds, VibrationEffect.DEFAULT_AMPLITUDE));
}
else {
v.vibrate(milliseconds);
}
}
}
public boolean has_touchscreen()
{
return getPackageManager().hasSystemFeature("android.hardware.touchscreen");
}
public boolean has_vibrator()
{
Vibrator v = (Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
if (v != null) {
return v.hasVibrator();
}
else {
return false;
}
}
public void start_draw()
{
if (paused) {
paused = false;
}
}
public String get_android_language()
{
return Locale.getDefault().getLanguage();
}
private static File[] list_dir_files = null;
public void list_dir_start(String path)
{
try {
int slash = path.lastIndexOf('/');
final String glob = path.substring(slash+1).replace("*", ".*"); // +1 works even if not found (-1+1 == 0)
String dir = path.substring(0, slash);
File f = new File(dir);
list_dir_files = f.listFiles(new FileFilter() {
public boolean accept(File f)
{
try {
if (f.getName().matches(glob)) {
return true;
}
else {
return false;
}
}
catch (Exception e) {
Log.d("TTH", "list_dir_start FileFilter throwing " + e.getMessage());
return false;
}
}
});
}
catch (Exception e) {
list_dir_files = null;
Log.d("TTH", "list_dir_start throwing " + e.getMessage());
}
}
public String list_dir_next()
{
if (list_dir_files == null) {
return "";
}
else if (list_dir_files.length == 0) {
list_dir_files = null;
return "";
}
else {
File f = list_dir_files[0];
String name = f.getName();
if (list_dir_files.length == 1) {
list_dir_files = null;
}
else {
File[] new_list = new File[list_dir_files.length-1];
for (int i = 1; i < list_dir_files.length; i++) {
new_list[i-1] = list_dir_files[i];
}
list_dir_files = new_list;
}
return name;
}
}
private static final String ARC_DEVICE_PATTERN = ".+_cheets|cheets_.+";
public boolean is_chromebook()
{
// Google uses this, so should work?
return Build.DEVICE != null && Build.DEVICE.matches(ARC_DEVICE_PATTERN);
}
private static final int RC_ACHIEVEMENT_UI = 9003;
public boolean show_achievements()
{
if (mAchievementsClient == null) {
return false;
}
mAchievementsClient.getAchievementsIntent().addOnSuccessListener(new OnSuccessListener<Intent>() {
#Override
public void onSuccess(Intent intent) {
startActivityForResult(intent, RC_ACHIEVEMENT_UI);
resume_after_showing_achievements();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(Exception e) {
resume_after_showing_achievements();
}
}).addOnCompleteListener(new OnCompleteListener<Intent>() {
#Override
public void onComplete(Task<Intent> task) {
resume_after_showing_achievements();
}
});
return true;
}
public void achieve(String id)
{
if (mAchievementsClient != null) {
mAchievementsClient.unlock(id);
}
}
private void startSignInIntent() {
GoogleSignInClient signInClient = GoogleSignIn.getClient(this, GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN);
Intent intent = signInClient.getSignInIntent();
startActivityForResult(intent, RC_SIGN_IN);
}
private void signInSilently() {
if (signin_failed == true || mAchievementsClient != null) {
return;
}
GoogleSignInOptions signInOptions = GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN;
GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(this);
if (GoogleSignIn.hasPermissions(account, signInOptions.getScopeArray())) {
// Already signed in.
// The signed in account is stored in the 'account' variable.
//GoogleSignInAccount signedInAccount = account;
onConnected(account);
}
else {
// Haven't been signed-in before. Try the silent sign-in first.
GoogleSignInClient signInClient = GoogleSignIn.getClient(this, signInOptions);
signInClient.silentSignIn().addOnCompleteListener(
this,
new OnCompleteListener<GoogleSignInAccount>() {
#Override
public void onComplete(#NonNull Task<GoogleSignInAccount> task) {
if (task.isSuccessful()) {
// The signed in account is stored in the task's result.
GoogleSignInAccount signedInAccount = task.getResult();
onConnected(signedInAccount);
}
else {
// Player will need to sign-in explicitly using via UI.
// See [sign-in best practices](http://developers.google.com/games/services/checklist) for guidance on how and when to implement Interactive Sign-in,
// and [Performing Interactive Sign-in](http://developers.google.com/games/services/android/signin#performing_interactive_sign-in) for details on how to implement
// Interactive Sign-in.
startSignInIntent();
}
}
}
);
}
}
public void start_google_play_games_services() {
/*
runOnUiThread(new Runnable() {
public void run() {
signInSilently();
}
});
*/
}
private void onConnected(GoogleSignInAccount googleSignInAccount) {
Log.d(TAG, "onConnected(): connected to Google APIs");
GamesClient gamesClient = Games.getGamesClient(this, googleSignInAccount);
gamesClient.setViewForPopups(findViewById(android.R.id.content));
gamesClient.setGravityForPopups(Gravity.TOP | Gravity.CENTER_HORIZONTAL);
mAchievementsClient = Games.getAchievementsClient(this, googleSignInAccount);
}
private void onDisconnected() {
Log.d(TAG, "onDisconnected()");
mAchievementsClient = null;
signin_failed = true;
}
}
When trying to create my Google maps I get the error:
error: incompatible types: Fragment cannot be converted to Activity
I have imported: import android.support.v4.app.Fragment; but I don't think that is the problem. The class from where it get's it information uses Fragments, however my methods need an Activity. I am trying to figure out how to correctly convert them. I have tried to convert the original Fragment class to FragmentActivity but then I get a error in my navigation where on the getTag() method. So I am stuck as to what I should do. I am still in the process of learning Android Studio.
the getTag() method
My code where I get the conversion error :
import android.Manifest;
import android.app.Activity;
import android.content.IntentSender;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationManager;
import android.os.Looper;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.content.ContextCompat;
import com.example.flow.displayClasses.WebscrapingScreens.GoogleMapsFragment;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.common.api.ResolvableApiException;
import com.google.android.gms.location.*;
import static android.content.Context.LOCATION_SERVICE;
public class LocationHandler {
private FusedLocationProviderClient fusedLocationProviderClient;
private LocationManager locationManager;
private LocationRequest locationRequest;
private LocationCallback locationCallback;
private LocationResultListener locationResultListener;
private Fragment activity;
//private Fragment activity;
// private Activity activity;
private int activityRequestCode;
private int permissionRequestCode;
private final String FINE_LOCATION = Manifest.permission.ACCESS_FINE_LOCATION;
private final String COARSE_LOCATION = Manifest.permission.ACCESS_COARSE_LOCATION;
private final int GRANTED = PackageManager.PERMISSION_GRANTED;
public LocationHandler(GoogleMapsFragment fragment, LocationResultListener locationResultListener,
int activityRequestCode, int permissionRequestCode) {
this.activity = fragment;
this.locationResultListener = locationResultListener;
this.activityRequestCode = activityRequestCode;
this.permissionRequestCode = permissionRequestCode;
initLocationVariables();
}
private void initLocationVariables() {
locationManager = (LocationManager) activity.getActivity().getSystemService(LOCATION_SERVICE);
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(activity);
locationRequest = LocationRequest
.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(0)
.setFastestInterval(0);
initLocationCallBack();
}
private void initLocationCallBack() {
locationCallback = new LocationCallback() {
#Override
public void onLocationResult(LocationResult locationResult) {
super.onLocationResult(locationResult);
locationResultListener.getLocation(locationResult.getLastLocation());
fusedLocationProviderClient.removeLocationUpdates(locationCallback);
}
};
}
private boolean isLocationEnabled() {
return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) &&
locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
}
private boolean isPermissionGranted(Activity activity) {
return ContextCompat.checkSelfPermission(activity, FINE_LOCATION) == GRANTED &&
ContextCompat.checkSelfPermission(activity, COARSE_LOCATION) == GRANTED;
}
private void requestPermission(Activity activity, int requestCode) {
String[] permissions = {FINE_LOCATION, COARSE_LOCATION};
ActivityCompat.requestPermissions(activity, permissions, requestCode);
}
private void promptUserToEnableLocation(final int requestCode) {
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder().addLocationRequest(locationRequest);
builder.setAlwaysShow(true);
LocationServices
.getSettingsClient(activity)
.checkLocationSettings(builder.build())
.addOnSuccessListener(locationSettingsResponse -> getLastKnownLocation())
.addOnFailureListener(e -> {
int status = ((ApiException) e).getStatusCode();
switch (status) {
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
try {
ResolvableApiException resolvableApiException = (ResolvableApiException) e;
resolvableApiException.startResolutionForResult(activity, requestCode);
} catch (IntentSender.SendIntentException exception) {
exception.printStackTrace();
}
break;
}
});
}
The error :
error: no suitable method found for getFusedLocationProviderClient(Fragment)
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(activity);
^
method LocationServices.getFusedLocationProviderClient(Activity) is not applicable
(argument mismatch; Fragment cannot be converted to Activity)
method LocationServices.getFusedLocationProviderClient(Context) is not applicable
(argument mismatch; Fragment cannot be converted to Context)
My GoogleMapsFragment :
public class GoogleMapsFragment extends Fragment implements OnMapReadyCallback, LocationResultListener, PlaceSelectedListener {
private static final int ACTIVITY_RQEUEST_CODE = 1000;
private static final int PERMISSION_REQUEST_CODE = 1000;
private static final float ZOOM_LEVEL = 15.0f;
private static final int REQUEST_LIMIT = 3;
private final String API_KEY = "AIzaSyApsuynhkRf3A7p3fgKQp01EEF8l4tggXQ";
private final String PLACES_REQUEST = "https://maps.googleapis.com/maps/api/place/nearbysearch/json?&key=" + API_KEY;
private GoogleMap googleMap;
private ClusterManager<MarkClusterItem> clusterManager;
private LocationHandler locationHandler;
private int requestCount;
private String nextPageToken;
private ProgressBar progressBar;
private List<GooglePlace> listPlaces = new ArrayList<>();
private FragmentActivity myContext;
#Override
public void onAttach(Activity activity) {
myContext=(FragmentActivity) activity;
super.onAttach(activity);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActivity().setContentView(R.layout.fragment_mapsgoogle);
progressBar = getActivity().findViewById(R.id.progressBar);
locationHandler = new LocationHandler(this, this, ACTIVITY_RQEUEST_CODE, PERMISSION_REQUEST_CODE);
FragmentManager fragManager = myContext.getSupportFragmentManager();
SupportMapFragment supportMapFragment = (SupportMapFragment) fragManager.findFragmentById(R.id.googleMap);
supportMapFragment.getMapAsync(this);
}
#Override
public void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == ACTIVITY_RQEUEST_CODE) {
if (resultCode == RESULT_OK) {
locationHandler.getUserLocation();
} else {
new AlertDialog.Builder(myContext)
.setTitle("Error")
.setMessage("Please enable location")
.setPositiveButton("Ok", (dialog, which) -> {
locationHandler.getUserLocation();
dialog.dismiss();
})
.setNegativeButton("Cancel", (dialog, which) -> dialog.dismiss())
.setCancelable(false)
.create()
.show();
}
}
}
#SuppressLint("NewApi")
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == PERMISSION_REQUEST_CODE) {
boolean isPermissionGranted = true;
for (int i = 0; i < permissions.length; i++) {
if (grantResults[i] != PermissionChecker.PERMISSION_GRANTED) {
isPermissionGranted = false;
break;
}
}
if (isPermissionGranted){
locationHandler.getUserLocation();
}else{
if (shouldShowRequestPermissionRationale(permissions[0]) && shouldShowRequestPermissionRationale(permissions[1])) {
locationHandler.getUserLocation();
} else {
new AlertDialog.Builder(myContext)
.setTitle("Error")
.setMessage("Please go to settings page to enable location permission")
.setPositiveButton("Go to Settings", (dialog, which) -> {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package",getActivity().getPackageName(), null);
intent.setData(uri);
startActivity(intent);
}).setNegativeButton("Cancel", (dialog, which) -> dialog.dismiss())
.setCancelable(false)
.create()
.show();
}
}
}
}
#Override
public void onMapReady(GoogleMap googleMap) {
this.googleMap = googleMap;
clusterManager = new ClusterManager<>(myContext, googleMap);
clusterManager.setRenderer(new MarkerClusterRenderer<>(myContext, googleMap, clusterManager));
setClusterClickListener();
googleMap.setOnMarkerClickListener(clusterManager);
googleMap.setOnCameraIdleListener(clusterManager);
locationHandler.getUserLocation();
}
private void setClusterClickListener(){
clusterManager.setOnClusterClickListener(cluster -> {
Collection<MarkClusterItem> clusterItems = cluster.getItems();
List<GooglePlace> list = new ArrayList<>();
for (MarkClusterItem markerClusterItem : clusterItems){
for (GooglePlace googlePlace : listPlaces){
if (googlePlace.getLatLng().equals(markerClusterItem.getPosition())){
list.add(googlePlace);
break;//no two places have the exact same latLng
}
}
}
new ListViewDialog(myContext, list, this).showDialog();
return true;
});
}
#SuppressLint("MissingPermission")
#Override
public void getLocation(Location location) {
googleMap.setMyLocationEnabled(true);
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, ZOOM_LEVEL));
progressBar.setVisibility(View.VISIBLE);
new PlaceRequest().execute(PLACES_REQUEST + "&radius=500&location=" + latLng.latitude + "," + latLng.longitude);
}
#Override
public void getPlace(GooglePlace googlePlace) {
Intent intent = new Intent(myContext, PlaceDetailsActivity.class);
intent.putExtra("placeid", googlePlace.getPlaceId());
startActivity(intent);
}
private class PlaceRequest extends AsyncTask<String, Integer, JSONArray> {
#Override
protected JSONArray doInBackground(String... params) {
try {
URL url = new URL(params[0]);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setRequestMethod("GET");
httpURLConnection.connect();
String line;
StringBuilder stringBuilder = new StringBuilder("");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream()));
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line);
}
JSONObject jsonObject = new JSONObject(stringBuilder.toString());
if (jsonObject.has("next_page_token")) {
nextPageToken = jsonObject.getString("next_page_token");
} else {
nextPageToken = "";
}
return jsonObject.getJSONArray("results");
} catch (Exception e) {
e.printStackTrace();
}
return new JSONArray();
}
#Override
protected void onPostExecute(JSONArray jsonArray) {
progressBar.setVisibility(View.GONE);
requestCount++;
try {
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
JSONObject location = jsonObject.getJSONObject("geometry").getJSONObject("location");
String placeId = jsonObject.getString("place_id");
String name = jsonObject.getString("name");
LatLng latLng = new LatLng(location.getDouble("lat"), location.getDouble("lng"));
GooglePlace googlePlace = new GooglePlace(name, placeId, latLng);
listPlaces.add(googlePlace);
MarkClusterItem markerClusterItem = new MarkClusterItem(latLng, name);
clusterManager.addItem(markerClusterItem);
}
clusterManager.cluster();
} catch (Exception e) {
e.printStackTrace();
}
if (requestCount < REQUEST_LIMIT && !nextPageToken.equals("")) {
progressBar.setVisibility(View.VISIBLE);
String url = PLACES_REQUEST + "&pagetoken=" + nextPageToken;
new Handler().postDelayed(() -> new PlaceRequest().execute(url), 2000);
}
}
}
}
You should avoid name and type dismatching like this
private Fragment activity;
It reduced code readability.
About the error: you trying to pass fragment instead of context.
To fix the error change
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(activity);
to this:
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(activity.getActivity());
I have this service which send my location to server and get some data from it.
package com.speed00.service;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.location.Location;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.support.v4.content.LocalBroadcastManager;
import android.text.TextUtils;
import android.widget.Toast;
import com.google.gson.Gson;
import com.speed00.R;
import com.speed00.constant.AppConstant;
import com.speed00.helper.FunctionHelper;
import com.speed00.model.achivment.StepHelper;
import com.speed00.model.ride.RideResultResponse;
import com.speed00.model.ride.UpdateLocationData;
import com.speed00.model.ride.UpdateLocationResponse;
import com.speed00.prefrences.MyPreferences;
import com.speed00.prefrences.MySharedPreference;
import com.speed00.retrofit.ApiUtils;
import com.speed00.stepdetucter.StepDetector;
import com.speed00.stepdetucter.StepListener;
import com.speed00.ui.activity.HomeActivity;
import com.speed00.utils.Logger;
import com.speed00.utils.MySensorEventListener;
import com.speed00.utils.NetworkConnection;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class MyService extends Service implements StepListener, SensorEventListener {
// constant
// run on another Thread to avoid crash
private Handler mHandler = new Handler();
// timer handling
private Timer mTimer = null;
private Double locationRange = 1.0;
private String oldDegree;
private boolean isServiceRunning;
private int numSteps = 0;
private final int FINAL_STEP = 15;
private SensorManager sensorManager;
private Sensor accel;
String speed_received = "0";
private boolean pedoMetterHasStarted = false;
String pLatitude;
String pLongitude;
private SensorEventListener eListener;
private Sensor accelerometer, magFieldSensor;
private StepDetector simpleStepDetector;
#Override
public IBinder onBind(Intent intent) {
return null;
}
private BroadcastReceiver message = new BroadcastReceiver() {
#Override
public void onReceive(Context context, final Intent intent) {
// TODO Auto-generated method stub
new Handler().post(new Runnable() {
#Override
public void run() {
speed_received = intent.getStringExtra("current speed");
Logger.e("speed__recv" + speed_received);
if (speed_received != null) {
// setSpeedValue(speed_received);//this method is calling to set speed.
//This method is calling to validate Timer For Ride
if (speed_received.equalsIgnoreCase("0")) {
if (!pedoMetterHasStarted) {
numSteps = 0;
statPedoMeter();
}
}
//Calculating distance value
String latitude = MySharedPreference.getInstance(MyService.this).getLatitude();
String longitude = MySharedPreference.getInstance(MyService.this).getLongitude();
if (TextUtils.isEmpty(pLatitude)) {
pLatitude = latitude;
pLongitude = longitude;
} else {
/*
* if distance is more then 2 km then its calculatiog.
*
* */
Location pLocation = new Location("P");
pLocation.setLongitude(Double.parseDouble(pLatitude));
pLocation.setLongitude(Double.parseDouble(pLongitude));
Location nLocation = new Location("N");
nLocation.setLongitude(Double.parseDouble(latitude));
nLocation.setLongitude(Double.parseDouble(longitude));
Logger.e("distance----" + pLocation.distanceTo(nLocation));
if (pLocation.distanceTo(nLocation) >= 10) {
pLatitude = latitude;
pLongitude = longitude;
}
}
}
}
});
}
};
#Override
public void onCreate() {
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
eListener = new MySensorEventListener(this, sensorManager);//for direction
accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
magFieldSensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
//callback sensor of ui
sensorManager.registerListener(eListener, accelerometer, SensorManager.SENSOR_DELAY_NORMAL);
sensorManager.registerListener(eListener, magFieldSensor, SensorManager.SENSOR_DELAY_NORMAL);
assert sensorManager != null;
accel = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
simpleStepDetector = new StepDetector();
simpleStepDetector.registerListener(this);
Toast.makeText(getApplicationContext(), "Service Started", Toast.LENGTH_SHORT).show();
isServiceRunning = true;
// Toast.makeText(getApplicationContext(), "service started", Toast.LENGTH_SHORT).show();
// cancel if already existed
if (mTimer != null) {
mTimer.cancel();
} else {
// recreate new
mTimer = new Timer();
}
// schedule task
// new Timer().scheduleAtFixedRate(new TimeDisplayTimerTask(), 100, NOTIFY_INTERVAL);
runLoop();
LocalBroadcastManager.getInstance(this).registerReceiver(message,
new IntentFilter("send"));
}
private void runLoop() {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
updateDriverLocation();
if (isServiceRunning)
runLoop();
}
}, 1000);
}
/*
*
* This method is calling to update driver location
* */
private void updateDriverLocation() {
//Get all user details data.
String userId = MySharedPreference.getInstance(getApplicationContext()).getDriverId();
String latitudeData = MySharedPreference.getInstance(getApplicationContext()).getLatitude();
String longitudeData = MySharedPreference.getInstance(getApplicationContext()).getLongitude();
String speedData = MySharedPreference.getInstance(getApplicationContext()).getSpeedData();//how to roinf
Logger.e("SERVER " + latitudeData + " " + longitudeData);
Logger.e("SPEED " + speedData);
String directionValue = MySharedPreference.getInstance(getApplicationContext()).getDirectionValue();
String speeding = MySharedPreference.getInstance(getApplicationContext()).getSpeeding();
String language = MyPreferences.newInstance(getApplicationContext()).getLanguage();//send speeding data to bakend.
String directionText = MySharedPreference.getInstance(getApplicationContext()).getDirectionText();
long driveTime = FunctionHelper.getDifference(MySharedPreference.getInstance(getApplicationContext()).getStartTime());
String validateUTurn = validateUTurn();
// Logger.e("update_request--" + request);
ApiUtils.getAPIService().updateDriverLocation(validateUTurn, directionText, speeding, "" + driveTime, language, userId,
AppConstant.START_RIDE, speedData, directionValue, latitudeData, longitudeData).enqueue(new Callback<UpdateLocationResponse>() {
#Override
public void onResponse(Call<UpdateLocationResponse> call, Response<UpdateLocationResponse> response) {
if (response.isSuccessful()) {
UpdateLocationResponse updateLocationResponse = response.body();
if (updateLocationResponse.getErrorCode().equalsIgnoreCase(AppConstant.ERROR_CODE)) {
if (updateLocationResponse.getData().size() > 0) {
UpdateLocationData updateLocationData = updateLocationResponse.getData().get(0);
String eventData = FunctionHelper.validateData(updateLocationData);
broadCastEventData(eventData, updateLocationResponse.getErrorCode());
broadCastResponseData(updateLocationResponse);
}
}
}
}
#Override
public void onFailure(Call<UpdateLocationResponse> call, Throwable t) {
}
});
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
/*
*
*This method is calling to validateUTurn.
*
*
* */
private String validateUTurn() {
String currentDegree = MySharedPreference.getInstance(this).getDirectionValue();
String uTurnStatus = "0";
if (TextUtils.isEmpty(oldDegree)) {
oldDegree = currentDegree;
uTurnStatus = "0";
return uTurnStatus;
} else {
if (oldDegree == "0.0") {
oldDegree = currentDegree;
}
if (Float.parseFloat(oldDegree) <= Float.parseFloat(currentDegree)) {
uTurnStatus = "1";
} else {
uTurnStatus = "0";
}
if (Float.parseFloat(oldDegree) == 360 || Float.parseFloat(oldDegree) > 270) {
if (Float.parseFloat(currentDegree) > 0 && Float.parseFloat(oldDegree) <= 90) {
uTurnStatus = "1";
}
}
oldDegree = currentDegree;
return uTurnStatus;
}
}
public synchronized void broadCastEventData(String eventData, String errorCode) {
Intent intent = new Intent("event_broad_cast");
intent.putExtra("data", eventData);
intent.putExtra("error", errorCode);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
/*
* This method is calling to broadcast event data
* */
/*
* This method is calling to broadcast event data
* */
public synchronized void broadCastResponseData(UpdateLocationResponse updateLocationData) {
Intent intent = new Intent("location_update");
Bundle args = new Bundle();
args.putSerializable("data", (Serializable) updateLocationData);
intent.putExtra("myvalue", args);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
#Override
public void onDestroy() {
super.onDestroy();
isServiceRunning = false;
LocalBroadcastManager.getInstance(this).unregisterReceiver(message);
// stopPedoMeter();
}
#Override
public void step(long timeNs) {
if (numSteps < 16)
Toast.makeText(this, "" + numSteps, Toast.LENGTH_SHORT).show();
saveStep();
if (calculateSteps()) {
stopRideAfter25step();
stopPedoMeter();//this method is calling to stop ResultActivity
} else if (Double.parseDouble(MySharedPreference.getInstance(this).getSpeedData()) > 10) {
MySharedPreference.getInstance(this).setSteps(new ArrayList<StepHelper>());
numSteps = 0;
} else {
Logger.e("stepsss " + numSteps);
numSteps = numSteps + 1;
}
}
private void stopRideAfter25step() {
MySharedPreference.getInstance(this).setSteps(new ArrayList<StepHelper>());
String speed = MySharedPreference.getInstance(this).getSpeedData();
String direction = MySharedPreference.getInstance(this).getDirectionValue();
String latitude = MySharedPreference.getInstance(this).getLatitude();
String longitude = MySharedPreference.getInstance(this).getLongitude();
String driverId = MySharedPreference.getInstance(this).getDriverId();
String language = MyPreferences.newInstance(this).getLanguage();
String speeding = MySharedPreference.getInstance(this).getSpeeding();
long driveTime = FunctionHelper.getDifference(MySharedPreference.getInstance(this).getStartTime());
//validate internet connection
if (NetworkConnection.isConnection(this)) {
stopRide("" + driveTime, language, speeding, driverId, latitude, longitude, AppConstant.STOP_RIDE, speed, direction);
} else {
Toast.makeText(this, getString(R.string.valid_please_check_network_connection), Toast.LENGTH_LONG).show();
}
}
public void stopRide(final String driveTime, final String languageKey, final String speedLimit, final String driverId, final String latitude, final String longitude, String rideStatus, final String speed, final String direction) {
String[] param = {driveTime, languageKey, speedLimit, driverId, speed, direction, latitude, longitude};
new stopLoc(this).execute(param);
}
#Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
simpleStepDetector.updateAccel(event.timestamp, event.values[0], event.values[1], event.values[2]);
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
private static class stopLoc extends AsyncTask<String[], Void, Void> {
Context mContext;
public stopLoc(Context mContext) {
this.mContext = mContext;
}
#Override
protected Void doInBackground(String[]... strings) {
Logger.e("stepsss stopingggg");
String driveTime = strings[0][0];
String languageKey = strings[0][1];
String speedLimit = strings[0][2];
String driverId = strings[0][3];
String speed = strings[0][4];
String direction = strings[0][5];
String latitude = strings[0][6];
String longitude = strings[0][7];
ApiUtils.getAPIService().stopTrip(driveTime, languageKey, speedLimit, driverId, AppConstant.STOP_RIDE, speed, direction, latitude, longitude).enqueue(new Callback<RideResultResponse>() {
#Override
public void onResponse(Call<RideResultResponse> call, Response<RideResultResponse> response) {
Logger.e("response----" + new Gson().toJson(response.body()));
if (response.isSuccessful()) {
String errorCode = response.body().getErrorCode();
if (errorCode.equalsIgnoreCase(AppConstant.ERROR_CODE)) {
tripSuccessData(response.body(), mContext);
} else {
Toast.makeText(mContext, "" + mContext.getString(R.string.text_some_erroroccurs), Toast.LENGTH_SHORT).show();
}
}
}
#Override
public void onFailure(Call<RideResultResponse> call, Throwable t) {
Toast.makeText(mContext, t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
return null;
}
}
public static void tripSuccessData(Object data, Context context) {
RideResultResponse resultResponse = (RideResultResponse) data;
if (resultResponse.getErrorCode().equalsIgnoreCase(AppConstant.ERROR_CODE)) {
FunctionHelper.enableUserIntraction();
HomeActivity.bSpeedStatus = false;
Intent intent = new Intent("trip_ended");
intent.putExtra("trip_info", resultResponse.getData().get(0));
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
((MyService) context).stopSelf();
} else {
Toast.makeText(context, resultResponse.getErrorMsg(), Toast.LENGTH_SHORT).show();
}
}
private boolean calculateSteps() {
ArrayList<StepHelper> arrayList = MySharedPreference.getInstance(this).getSteps();
ArrayList<StepHelper> newList = new ArrayList<>();
for (int i = 0; i < arrayList.size(); i++) {
long seconds = FunctionHelper.getDifference(arrayList.get(i).getTime());
if ((int) seconds < 180) {
newList.add(arrayList.get(i));
}
}
if (numSteps - newList.get(0).getSteps() >= FINAL_STEP) {
return true;
} else {
MySharedPreference.getInstance(this).setSteps(newList);
return false;
}
}
private void saveStep() {
ArrayList<StepHelper> arrayList = MySharedPreference.getInstance(this).getSteps();
if (arrayList == null) {
arrayList = new ArrayList<>();
}
arrayList.add(new StepHelper(FunctionHelper.getCurrentDateWitTime(), numSteps));
MySharedPreference.getInstance(this).setSteps(arrayList);
}
private void statPedoMeter() {
// Toast.makeText(this, "start count", Toast.LENGTH_SHORT).show();
pedoMetterHasStarted = true;
MySharedPreference.getInstance(this).setStartPedoMeterTime(FunctionHelper.getCurrentDateWitTime());//store current time
if (sensorManager != null)
sensorManager.registerListener(this, accel, SensorManager.SENSOR_DELAY_NORMAL);
}
/*
* This method is calling to stop pedo meter
*
* */
private void stopPedoMeter() {
numSteps = 0;
pedoMetterHasStarted = false;
sensorManager.unregisterListener(this, accelerometer);
sensorManager.unregisterListener(this, accel);
sensorManager.unregisterListener(this, magFieldSensor);
sensorManager = null;
}
class TimeDisplayTimerTask extends TimerTask {
#Override
public void run() {
// run on another thread
mHandler.post(new Runnable() {
#Override
public void run() {
Logger.e("MyService --- " + "isRuning");
if (HomeActivity.bSpeedStatus) {
updateDriverLocation();
}
}
});
}
}
}
My app starts and use only 170 MB , but after starting this service , it becomes 220 MB and after finishing it, it still 220 and if i open it again , ram become 240 and if i finish it still 240 and if i open it again it become 260 and so on until app crash
what's the wrong in the service ?
i make sure that it's stopped but don't know why ram not reduced after this service is finished
Try this approache, don't put the stopSelf() inside a static method. Instead, you should call startService again and add an action to the Intent.
So this is how an example actionable service should look like:
public class ExampleService
extends Service {
public static final String START_SERVICE_ACTION = "com.example.action.START_SERVICE";
public static final String STOP_SERVICE_ACTION = "com.example.action.STOP_SERVICE";
#Override
public void onCreate() {
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
String intentAction = intent.getAction();
switch (intentAction) {
case START_SERVICE_ACTION:
//
break;
case STOP_SERVICE_ACTION:
stopSelf();
break;
}
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public IBinder onBind(Intent intent) {
// Used only in case if services are bound (Bound Services).
return null;
}
}
Interact with the Service from somewhere:
Start with it like this:
Intent service = new Intent(context, ExampleService.class);
service.setAction(NotificationService.START_SERVICE_ACTION);
startService(service);
Stop it like this:
Intent service = new Intent(context, ExampleService.class);
service.setAction(NotificationService.STOP_SERVICE_ACTION);
startService(service);
You don't really need to pass the START_SERVICE_ACTION in this example, just added it to better understand the design.
I am having trouble with my app that uses Google's Real-time Multiplayer. When you launch the app, it just crashes. I added the crash log at the bottom...
I was able to find out that the problem was when I called mGoogleApiClient.connect();
Here is my code:
//(Your package here:)
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;
import android.widget.Toast;
import com.birdprograms.multiplayer.BaseGameUtils.src.main.java.com.google.example.games.basegameutils.BaseGameUtils;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.games.Games;
import com.google.android.gms.games.GamesStatusCodes;
import com.google.android.gms.games.multiplayer.Invitation;
import com.google.android.gms.games.multiplayer.OnInvitationReceivedListener;
import com.google.android.gms.games.multiplayer.Participant;
import com.google.android.gms.games.multiplayer.realtime.RealTimeMessage;
import com.google.android.gms.games.multiplayer.realtime.RealTimeMessageReceivedListener;
import com.google.android.gms.games.multiplayer.realtime.Room;
import com.google.android.gms.games.multiplayer.realtime.RoomConfig;
import com.google.android.gms.games.multiplayer.realtime.RoomStatusUpdateListener;
import com.google.android.gms.games.multiplayer.realtime.RoomUpdateListener;
import com.google.android.gms.plus.Plus;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class MyActivity extends Activity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, View.OnClickListener, RealTimeMessageReceivedListener, RoomUpdateListener, RoomStatusUpdateListener, OnInvitationReceivedListener{
private static final int RC_SIGN_IN = 9001;
private GoogleApiClient mGoogleApiClient;
private boolean mResolvingConnectionFailure = false;
private boolean mSignInClicked = false;
private boolean mAutoStartSignInFlow = true;
String mRoomId = null;
ArrayList<Participant> mParrticipants = null;
String mMyId = null;
byte[] mMsgBuf = new byte[2];
private TextView textView;
private TextView myscoretxt;
private TextView urscoretxt;
final static int[] CLICKALBES = {
R.id.button,R.id.button2,R.id.button3
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Plus.API).addScope(Plus.SCOPE_PLUS_LOGIN)
.addApi(Games.API).addScope(Games.SCOPE_GAMES)
.build();
for (int id : CLICKALBES){
findViewById(id).setOnClickListener(this);
}
}
private void startQuickGame(){
final int MIN_OPPONENTS = 1, MAX_OPPONENTS = 1;
Bundle autoMatchCriteria = RoomConfig.createAutoMatchCriteria(MIN_OPPONENTS,
MAX_OPPONENTS,0);
RoomConfig.Builder rtmConfigBuilder = RoomConfig.builder(this);
rtmConfigBuilder.setMessageReceivedListener(this);
rtmConfigBuilder.setRoomStatusUpdateListener(this);
rtmConfigBuilder.setAutoMatchCriteria(autoMatchCriteria);
changedisplay(1);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
resetGameVars();
Games.RealTimeMultiplayer.create(mGoogleApiClient,rtmConfigBuilder.build());
}
#Override
public void onActivityResult(int requestCode, int responseCode,Intent intent){
super.onActivityResult(requestCode,responseCode,intent);
switch(requestCode){
case RC_SIGN_IN:
mSignInClicked = false;
mResolvingConnectionFailure = false;
if(responseCode == RESULT_OK){
mGoogleApiClient.connect();
} else {
BaseGameUtils.showActivityResultError(this, requestCode, requestCode, R.string.signin_other_error);
}
break;
};
super.onActivityResult(requestCode,responseCode,intent);
}
#Override
public void onStop(){
leaveRoom();
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
if (mGoogleApiClient == null || !mGoogleApiClient.isConnected()){
changedisplay(0);
}
super.onStop();
}
#Override
public void onStart(){
changedisplay(0);
if (mGoogleApiClient != null && mGoogleApiClient.isConnected()){
} else {
mGoogleApiClient.connect();
}
super.onStart();
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent e){
if (keyCode == KeyEvent.KEYCODE_BACK && findViewById(R.id.button).getVisibility() == View.VISIBLE){
leaveRoom();
return true;
}
return super.onKeyDown(keyCode, e);
}
void leaveRoom(){
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
resetGameVars();
if(mRoomId != null){
Games.RealTimeMultiplayer.leave(mGoogleApiClient, this, mRoomId);
mRoomId = null;
findViewById(R.id.button).setVisibility(View.VISIBLE);
changedisplay(0);
textView = (TextView)findViewById(R.id.textView3);
myscoretxt = (TextView)findViewById(R.id.textView);
urscoretxt = (TextView)findViewById(R.id.textView2);
}
}
#Override
public void onClick(View view) {
switch (view.getId()){
case R.id.button:
mSignInClicked = true;
mGoogleApiClient.connect();
break;
case R.id.button2:
startQuickGame();
startGame(true);
break;
case R.id.button3:
scoreOnePoint();
}
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
if (mResolvingConnectionFailure){
return;
}
if (mSignInClicked || mAutoStartSignInFlow){
mAutoStartSignInFlow = false;
mSignInClicked = false;
mResolvingConnectionFailure = BaseGameUtils.resolveConnectionFailure(this,mGoogleApiClient,connectionResult,RC_SIGN_IN,getString(R.string.signin_other_error));
}
changedisplay(1);
}
void updateRoom(Room room){
if(room != null){
mParrticipants = room.getParticipants();
}
if (mParrticipants != null){
updatePeerScoresDisplay();
}
}
#Override
public void onConnectedToRoom(Room room) {
mRoomId = room.getRoomId();
mParrticipants = room.getParticipants();
mMyId = room.getParticipantId(Games.Players.getCurrentPlayerId(mGoogleApiClient));
}
#Override
public void onDisconnectedFromRoom(Room room) {
mRoomId = null;
showGameError();
}
void showGameError(){
BaseGameUtils.makeSimpleDialog(this,getString(R.string.game_problem));
changedisplay(0);
}
#Override
public void onJoinedRoom(int i, Room room) {
if(i != GamesStatusCodes.STATUS_OK){
showGameError();
return;
}
}
#Override
public void onRoomConnected(int i, Room room) {
if(i != GamesStatusCodes.STATUS_OK){
showGameError();
return;
}
updateRoom(room);
}
int mSecondsLeft = -1;
final static int GAME_DDURATION = 20;
int mScore = 0;
void resetGameVars(){
mSecondsLeft = GAME_DDURATION;
mScore = 0;
mParticipantScore.clear();
mFinishedParticipants.clear();
}
void startGame(boolean multiplayer){
updateScoreDisplay();
broadcastScore(false);
changedisplay(1);
final Handler h = new Handler();
h.postDelayed(new Runnable() {
#Override
public void run() {
if (mSecondsLeft <= 0)
return;
gameTick();
h.postDelayed(this, 1000);
}
}, 1000);
}
void gameTick(){
if(mSecondsLeft > 0)
--mSecondsLeft;
textView.setText("Time Left: "+mSecondsLeft+" seconds");
if (mSecondsLeft <= 0){
changedisplay(0);
broadcastScore(true);
}
}
void scoreOnePoint(){
if(mSecondsLeft <= 0)
return;
++mScore;
updateScoreDisplay();
updatePeerScoresDisplay();
broadcastScore(false);
}
Map<String, Integer> mParticipantScore = new HashMap<String, Integer>();
Set<String> mFinishedParticipants = new HashSet<String>();
#Override
public void onRealTimeMessageReceived(RealTimeMessage realTimeMessage) {
byte[] buf = realTimeMessage.getMessageData();
String sender = realTimeMessage.getSenderParticipantId();
if(buf[0] == 'F' || buf[0] == 'U'){
int existingScore = mParticipantScore.containsKey(sender) ?
mParticipantScore.get(sender) : 0;
int thisScore = (int) buf[1];
if(thisScore > existingScore){
mParticipantScore.put(sender, thisScore);
}
updatePeerScoresDisplay();
if((char) buf[0] == 'F'){
mFinishedParticipants.add(realTimeMessage.getSenderParticipantId());
}
}
}
void broadcastScore(boolean finalScore){
mMsgBuf[0] = (byte) (finalScore ? 'F' : 'U');
mMsgBuf[1] = (byte) mScore;
for(Participant p : mParrticipants){
if(p.getParticipantId().equals(mMyId))
continue;
if (p.getStatus() != Participant.STATUS_JOINED)
continue;
if (finalScore){
Games.RealTimeMultiplayer.sendReliableMessage(mGoogleApiClient, null, mMsgBuf, mRoomId, p.getParticipantId());
} else {
Games.RealTimeMultiplayer.sendUnreliableMessage(mGoogleApiClient, mMsgBuf, mRoomId, p.getParticipantId());
}
}
}
void updateScoreDisplay(){
myscoretxt.setText("Your Score: "+fomatScore(mScore));
}
String fomatScore(int i){
if(i<0)
i=0;
String s = String.valueOf(i);
return s.length() == 1 ? "00" + s : s.length() == 2 ? "0" + s : s;
}
void updatePeerScoresDisplay(){
if(mRoomId != null){
for (Participant p : mParrticipants){
String pid = p.getParticipantId();
if(pid.equals(mMyId))
continue;
if (p.getStatus() != Participant.STATUS_JOINED)
continue;
int score = mParticipantScore.containsKey(pid) ? mParticipantScore.get(pid) : 0;
urscoretxt.setText("Opponents Score: "+fomatScore(score));
}
}
}
void changedisplay(int i){
if(i == 0){
findViewById(R.id.button).setVisibility(View.VISIBLE);
findViewById(R.id.button2).setVisibility(View.VISIBLE);
findViewById(R.id.button3).setVisibility(View.GONE);
findViewById(R.id.textView).setVisibility(View.GONE);
findViewById(R.id.textView2).setVisibility(View.GONE);
findViewById(R.id.textView3).setVisibility(View.GONE);
}
else{
findViewById(R.id.button).setVisibility(View.GONE);
findViewById(R.id.button2).setVisibility(View.GONE);
findViewById(R.id.button3).setVisibility(View.VISIBLE);
findViewById(R.id.textView).setVisibility(View.VISIBLE);
findViewById(R.id.textView2).setVisibility(View.VISIBLE);
findViewById(R.id.textView3).setVisibility(View.VISIBLE);
}
}
}
I have removed several callbacks for readers sake that did not cause the problem for sure!
If you read the whole thing, then thank you for your patience. :)
Any help, or suggestions would be helpful. Thanks!
-Nathan
Edit
Here is the crash log:
04-22 09:28:00.320 19247-19247/com.birdprograms.multiplayerdemo E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.birdprograms.multiplayerdemo, PID: 19247
java.lang.IllegalStateException: A fatal developer error has occurred. Check the logs for further information.
at com.google.android.gms.internal.jl$h.b(Unknown Source)
at com.google.android.gms.internal.jl$h.g(Unknown Source)
at com.google.android.gms.internal.jl$b.hy(Unknown Source)
at com.google.android.gms.internal.jl$a.handleMessage(Unknown Source)
at android.os.Handler.dispatchMessage(Handler.java:110)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:5323)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:825)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:641)
at dalvik.system.NativeStart.main(Native Method)
Your manifest is missing
<meta-data
android:name="com.google.android.gms.games.APP_ID"
android:value="#string/app_id" />
// this is required if your RequestedClients is using AppStateManager.SCOPE_APP_STATE
<meta-data
android:name="com.google.android.gms.games.appstate.APP_ID"
android:value="#string/app_id" />
I am using some of the samples provided on line which show how to write to a device. What i want to do is as it loads up the device services and characteristics the app writes data to the tag, rather than open up a dialog to do this.
Can anyone shed some light on this please as i am new to Android development.
I have tried to add edit the code within the following section...
private void displayGattServices(List<BluetoothGattService> gattServices) {
but this line causes the app to crash...
byte[] bytes = DeviceControlActivity.this.mWriteCharacteristic.getValue();
As i tried to move the write part of the code from
public class BleCharacterDialogFragment extends DialogFragment
as i thought that would write to the BLE device.
All help is much appreciated, thanks. Below is the code i have. It came from https://github.com/suzp1984/Light_BLE originally.
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.PendingIntent;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
//import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ExpandableListView;
import android.widget.SimpleExpandableListAdapter;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import tkr.lightble.utils.Log;
/**
* For a given BLE device, this Activity provides the user interface to connect, display data,
* and display GATT services and characteristics supported by the device. The Activity
* communicates with {#code BluetoothLeService}, which in turn interacts with the
* Bluetooth LE API.
*/
public class DeviceControlActivity extends Activity {
public static final String EXTRAS_DEVICE_NAME = "DEVICE_NAME";
public static final String EXTRAS_DEVICE_ADDRESS = "DEVICE_ADDRESS";
private TextView mConnectionState;
private TextView mDataField;
private TextView mRssiField;
private String mDeviceName;
private String mDeviceAddress;
private ExpandableListView mGattServicesList;
private BluetoothLeService mBluetoothLeService;
private ArrayList<ArrayList<BluetoothGattCharacteristic>> mGattCharacteristics =
new ArrayList<ArrayList<BluetoothGattCharacteristic>>();
private boolean mConnected = false;
private BluetoothGattCharacteristic mNotifyCharacteristic;
private BluetoothGattCharacteristic mWriteCharacteristic;
private final String LIST_NAME = "NAME";
private final String LIST_UUID = "UUID";
// Code to manage Service lifecycle.
private final ServiceConnection mServiceConnection = new ServiceConnection() {
#Override
public void onServiceConnected(ComponentName componentName, IBinder service) {
mBluetoothLeService = ((BluetoothLeService.LocalBinder) service).getService();
if (!mBluetoothLeService.initialize()) {
Log.e("Unable to initialize Bluetooth");
finish();
}
// Automatically connects to the device upon successful start-up initialization.
mBluetoothLeService.connect(mDeviceAddress);
mBluetoothLeService.setBLEServiceCb(mDCServiceCb);
}
#Override
public void onServiceDisconnected(ComponentName componentName) {
mBluetoothLeService = null;
}
};
// If a given GATT characteristic is selected, check for supported features. This sample
// demonstrates 'Read' and 'Notify' features. See
// http://d.android.com/reference/android/bluetooth/BluetoothGatt.html for the complete
// list of supported characteristic features.
private final ExpandableListView.OnChildClickListener servicesListClickListner =
new ExpandableListView.OnChildClickListener() {
#TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
#Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition,
int childPosition, long id) {
if (mGattCharacteristics != null) {
final BluetoothGattCharacteristic characteristic =
mGattCharacteristics.get(groupPosition).get(childPosition);
final int charaProp = characteristic.getProperties();
if ((charaProp & BluetoothGattCharacteristic.PROPERTY_READ) > 0) {
// If there is an active notification on a characteristic, clear
// it first so it doesn't update the data field on the user interface.
Log.d("BluetoothGattCharacteristic has PROPERTY_READ, so send read request");
if (mNotifyCharacteristic != null) {
mBluetoothLeService.setCharacteristicNotification(
mNotifyCharacteristic, false);
mNotifyCharacteristic = null;
}
mBluetoothLeService.readCharacteristic(characteristic);
}
if ((charaProp & BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
Log.d("BluetoothGattCharacteristic has PROPERTY_NOTIFY, so send notify request");
mNotifyCharacteristic = characteristic;
mBluetoothLeService.setCharacteristicNotification(
characteristic, true);
}
if (((charaProp & BluetoothGattCharacteristic.PROPERTY_WRITE) |
(charaProp & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE)) > 0) {
Log.d("BluetoothGattCharacteristic has PROPERY_WRITE | PROPERTY_WRITE_NO_RESPONSE");
mWriteCharacteristic = characteristic;
// popup an dialog to write something.
showCharactWriteDialog();
}
return true;
}
return false;
}
};
private void showCharactWriteDialog() {
DialogFragment newFrame = new BleCharacterDialogFragment();
newFrame.show(getFragmentManager(), "blewrite");
}
private void writeCharacteristic(BluetoothGattCharacteristic characteristic) {
if (mBluetoothLeService != null) {
mBluetoothLeService.writeCharacteristic(characteristic);
}
}
private void clearUI() {
mGattServicesList.setAdapter((SimpleExpandableListAdapter) null);
mDataField.setText(R.string.no_data);
}
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.gatt_services_characteristics);
final Intent intent = getIntent();
mDeviceName = intent.getStringExtra(EXTRAS_DEVICE_NAME);
mDeviceAddress = intent.getStringExtra(EXTRAS_DEVICE_ADDRESS);
// Sets up UI references.
((TextView) findViewById(R.id.device_address)).setText(mDeviceAddress);
mGattServicesList = (ExpandableListView) findViewById(R.id.gatt_services_list);
mGattServicesList.setOnChildClickListener(servicesListClickListner);
mConnectionState = (TextView) findViewById(R.id.connection_state);
mDataField = (TextView) findViewById(R.id.data_value);
mRssiField = (TextView) findViewById(R.id.signal_rssi);
getActionBar().setTitle(mDeviceName);
getActionBar().setDisplayHomeAsUpEnabled(true);
Intent gattServiceIntent = new Intent(this, BluetoothLeService.class);
bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
}
#Override
protected void onResume() {
super.onResume();
//registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter());
if (mBluetoothLeService != null) {
final boolean result = mBluetoothLeService.connect(mDeviceAddress);
Log.d("Connect request result=" + result);
}
}
#Override
protected void onPause() {
super.onPause();
//unregisterReceiver(mGattUpdateReceiver);
}
#Override
protected void onDestroy() {
super.onDestroy();
unbindService(mServiceConnection);
mBluetoothLeService = null;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.gatt_services, menu);
if (mConnected) {
menu.findItem(R.id.menu_connect).setVisible(false);
menu.findItem(R.id.menu_disconnect).setVisible(true);
} else {
menu.findItem(R.id.menu_connect).setVisible(true);
menu.findItem(R.id.menu_disconnect).setVisible(false);
}
return true;
}
#TargetApi(Build.VERSION_CODES.ECLAIR)
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()) {
case R.id.menu_connect:
mBluetoothLeService.connect(mDeviceAddress);
return true;
case R.id.menu_disconnect:
mBluetoothLeService.disconnect();
return true;
case android.R.id.home:
onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
private void updateConnectionState(final int resourceId) {
runOnUiThread(new Runnable() {
#Override
public void run() {
mConnectionState.setText(resourceId);
}
});
}
private void displayData(String data) {
if (data != null) {
mDataField.setText(data);
}
}
private void displayRssi(String rssi) {
if (rssi != null) {
//Log.d("-- dispaly Rssi: " + rssi);
mRssiField.setText(rssi);
}
}
// Demonstrates how to iterate through the supported GATT Services/Characteristics.
// In this sample, we populate the data structure that is bound to the ExpandableListView
// on the UI.
#TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
private void displayGattServices(List<BluetoothGattService> gattServices) {
Log.d("displayGATTServices");
if (gattServices == null) return;
String uuid = null;
String unknownServiceString = getResources().getString(R.string.unknown_service);
String unknownCharaString = getResources().getString(R.string.unknown_characteristic);
ArrayList<HashMap<String, String>> gattServiceData = new ArrayList<HashMap<String, String>>();
ArrayList<ArrayList<HashMap<String, String>>> gattCharacteristicData
= new ArrayList<ArrayList<HashMap<String, String>>>();
mGattCharacteristics = new ArrayList<ArrayList<BluetoothGattCharacteristic>>();
// Loops through available GATT Services.
for (BluetoothGattService gattService : gattServices) {
HashMap<String, String> currentServiceData = new HashMap<String, String>();
uuid = gattService.getUuid().toString();
currentServiceData.put(
LIST_NAME, SampleGattAttributes.lookup(uuid, unknownServiceString));
currentServiceData.put(LIST_UUID, uuid);
gattServiceData.add(currentServiceData);
ArrayList<HashMap<String, String>> gattCharacteristicGroupData =
new ArrayList<HashMap<String, String>>();
List<BluetoothGattCharacteristic> gattCharacteristics =
gattService.getCharacteristics();
ArrayList<BluetoothGattCharacteristic> charas =
new ArrayList<BluetoothGattCharacteristic>();
// Loops through available Characteristics.
for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
charas.add(gattCharacteristic);
HashMap<String, String> currentCharaData = new HashMap<String, String>();
uuid = gattCharacteristic.getUuid().toString();
currentCharaData.put(
LIST_NAME, SampleGattAttributes.lookup(uuid, unknownCharaString));
currentCharaData.put(LIST_UUID, uuid);
gattCharacteristicGroupData.add(currentCharaData);
}
mGattCharacteristics.add(charas);
gattCharacteristicData.add(gattCharacteristicGroupData);
}
SimpleExpandableListAdapter gattServiceAdapter = new SimpleExpandableListAdapter(
this,
gattServiceData,
android.R.layout.simple_expandable_list_item_2,
new String[] {LIST_NAME, LIST_UUID},
new int[] { android.R.id.text1, android.R.id.text2 },
gattCharacteristicData,
android.R.layout.simple_expandable_list_item_2,
new String[] {LIST_NAME, LIST_UUID},
new int[] { android.R.id.text1, android.R.id.text2 }
);
mGattServicesList.setAdapter(gattServiceAdapter);
}
private DCServiceCb mDCServiceCb = new DCServiceCb();
public class DCServiceCb implements BluetoothLeService.BLEServiceCallback {
#Override
public void displayRssi(final int rssi) {
runOnUiThread(new Runnable() {
#Override
public void run() {
DeviceControlActivity.this.displayRssi(String.valueOf(rssi));
}
}
);
}
#Override
public void displayData(final String data) {
runOnUiThread(new Runnable() {
#Override
public void run() {
DeviceControlActivity.this.displayData(data);
}
});
}
#Override
public void notifyConnectedGATT() {
runOnUiThread(new Runnable() {
#Override
public void run() {
mConnected = true;
updateConnectionState(R.string.connected);
invalidateOptionsMenu();
}
});
}
#Override
public void notifyDisconnectedGATT() {
runOnUiThread(new Runnable() {
#Override
public void run() {
mConnected = false;
updateConnectionState(R.string.disconnected);
invalidateOptionsMenu();
clearUI();
}
});
}
#Override
public void displayGATTServices() {
Log.d("displayGATTServices.");
runOnUiThread(new Runnable() {
#Override
public void run() {
if (mBluetoothLeService != null) {
DeviceControlActivity.this.displayGattServices(
mBluetoothLeService.getSupportedGattServices());
}
}
});
}
}
public class BleCharacterDialogFragment extends DialogFragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.write_charact_dialog, container, false);
final EditText ed = (EditText) v.findViewById(R.id.charact_value);
Button ok = (Button) v.findViewById(R.id.dialog_confirm);
Button cancel = (Button) v.findViewById(R.id.dialog_cancel);
ok.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// write characterist here.
String str = ed.getText().toString();
//mWriteCharactristc.
byte[] strBytes = str.getBytes();
byte[] bytes;
bytes = DeviceControlActivity.this.mWriteCharacteristic.getValue();
//mWriteCharacteristic.
if (strBytes == null) {
Log.w("Cannot get Value from EditText Widget");
dismiss();
return;
}
if (bytes == null) {
// maybe just write a byte into GATT
Log.w("Cannot get Values from mWriteCharacteristic.");
dismiss();
return;
} else if (bytes.length <= strBytes.length) {
for(int i = 0; i < bytes.length; i++) {
bytes[i] = strBytes[i];
}
} else {
for (int i = 0; i < strBytes.length; i++) {
bytes[i] = strBytes[i];
}
}
DeviceControlActivity.this.mWriteCharacteristic.setValue(bytes);
DeviceControlActivity.this.writeCharacteristic(
DeviceControlActivity.this.mWriteCharacteristic
);
dismiss();
return;
}
});
cancel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dismiss();
}
});
return v;
}
}
}
To write a value to a device you have to know tow things
1-Service UUID
2-Characteristic UUID
You can read/write a value from/to Characteristic UUID
Here is the sample code to write a value to Characteristic.
public void writeCharacteristic(byte[] value)
{
BluetoothGattService service = mBluetoothGatt.getService(YOUR_SEVICE_UUID);
if (service == null) {
System.out.println("service null"); return;
}
BluetoothGattCharacteristic characteristic = service.getCharacteristic(YOUR_CHARACTERISTIC_UUID);
if (characteristic == null) {
System.out.println("characteristic null"); return;
}
characteristic.setValue(value);
boolean status = mBluetoothGatt.writeCharacteristic(characteristic);
System.out.println("Write Status: " + status);
}