Related
this is my server code
i am getting an error on my android phone when i clicked the device address
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import javax.bluetooth.*;
import javax.microedition.io.*;
public class ServerSide {
//private static LocalDevice localDevice;
static LocalDevice localDevice;
DiscoveryAgent agent;
private void startServer() throws IOException{
UUID uuid = new UUID("112f8dbf1e46442292b6796539467bc9", false);
String connectionString = "btspp://localhost:" + uuid
+";name=SampleSPPServer";
//open server url
StreamConnectionNotifier streamConnNotifier =
(StreamConnectionNotifier)Connector.open( connectionString );
System.out.println("\nServer Started. Waiting for clients to
connect...");
StreamConnection connection=streamConnNotifier.acceptAndOpen();
RemoteDevice dev = RemoteDevice.getRemoteDevice(connection);
System.out.println("Remote device address:
"+dev.getBluetoothAddress());
System.out.println("Remote device name:
"+dev.getFriendlyName(true));
}
public static void main(String[] args) {
//display local device address and name
try{
localDevice = LocalDevice.getLocalDevice();
System.out.println("Address: "+localDevice.getBluetoothAddress());
System.out.println("Name: "+localDevice.getFriendlyName());
}catch(Exception e){
System.err.println(e.toString());
System.err.println(e.getStackTrace());
e.printStackTrace();}
try{
ServerSide sampleSPPServer=new ServerSide();
sampleSPPServer.startServer();
}catch(Exception e){
System.err.println(e.toString());
System.err.println(e.getStackTrace());
e.printStackTrace();}
}
}
**************************************************************
and this is my client(android) code
package client.side;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
public class ClientSideActivity extends Activity {
int REQUEST_ENABLE_BT = 0;
private BluetoothAdapter mBluetoothAdapter;
private ArrayAdapter<String> mArrayAdapter;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button btn1 = (Button)findViewById(R.id.button1);
Button btn2 = (Button)findViewById(R.id.button2);
final ListView lv1 = (ListView)findViewById(R.id.listView1);
final TextView out = (TextView)findViewById(R.id.textView1);
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mArrayAdapter = new
ArrayAdapter<String>(this,android.R.layout.simple_list_item_1);
if (!mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new
Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent,
REQUEST_ENABLE_BT);
}
out.setText(null);
btn1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
out.setText("Paired Devices");
Set<BluetoothDevice> pairedDevices =
mBluetoothAdapter.getBondedDevices();
if (pairedDevices.size() > 0){
for(BluetoothDevice device : pairedDevices){
mArrayAdapter.add(device.getName() + "\n" +
device.getAddress());
}
}
lv1.setAdapter(mArrayAdapter);
}
});
btn2.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
out.setText("Discovered Devices");
mBluetoothAdapter.startDiscovery();
Toast msg = Toast.makeText(ClientSideActivity.this, "Discovering
Devices please wait.", Toast.LENGTH_LONG);
msg.show();
final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
// When discovery finds a device
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// Get the BluetoothDevice object from the Intent
BluetoothDevice device =
intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// Add the name and address to an array adapter to show
in a ListView
mArrayAdapter.add(device.getAddress());
} }
};
// Register the BroadcastReceiver
IntentFilter filter = new
IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter); // Don't forget to unregister
during onDestroy
}
});
lv1.setOnItemClickListener(new OnItemClickListener()
{
public void onItemClick(AdapterView<?> arg0, View arg1, int
position,long id)
{
out.setText(arg0.getItemAtPosition(position).toString());
BluetoothDevice remoteDev = (BluetoothDevice)
arg0.getItemAtPosition(position);
ConnectThread conDev = new ConnectThread(remoteDev);
conDev.start();
}
});
}
public class ConnectThread extends Thread {
private final UUID MY_UUID =
UUID.fromString("112f8dbf1e46442292b6796539467bc9");
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
public ConnectThread(BluetoothDevice device) {
// Use a temporary object that is later assigned to
mmSocket,
// because mmSocket is final
BluetoothSocket tmp = null;
mmDevice = device;
try {
// MY_UUID is the app's UUID string, also used by the
server code
tmp =
device.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) { }
mmSocket = tmp;
}
public void run() {
// Cancel discovery because it will slow down the
connection
mBluetoothAdapter.cancelDiscovery();
try {
// Connect the device through the socket. This will
block
// until it succeeds or throws an exception
mmSocket.connect();
} catch (IOException connectException) {
// Unable to connect; close the socket and get out
try {
mmSocket.close();
} catch (IOException closeException) { }
return;
}
// Do work to manage the connection (in a separate
thread)
}
/** Will cancel an in-progress connection, and close the
socket */
}
}
I am trying to make an app that on launch reads the current on/off(1,0) value of /sys/class/mdnie/mdnie/negative, then changes it to "0 or 1. Someone suggested the below, and I tried it and it does nothing any help is apreciated. Obvously I am a beginner and barely know how to write code but hey gotta start somewhere, this is for a visually impaired friend to toggle negative color mode by assigning a shortcut key to the app. I think it has to do with needing root permision to edit those settings.
Code:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import android.app.Activity;
import android.os.Bundle;
public class ToggleNegativeColorsActivity extends Activity {
private static final String FILEPATH = "/sys/class/mdnie/mdnie/negative";
@Override
public void onCreate(Bundle savedInstanceState) {
try {
String value = readFileAsString(FILEPATH);
if ("1".equals(value.trim())) {
writeStringToFile(FILEPATH, "0");
}
else {
writeStringToFile(FILEPATH, "1");
}}
catch (IOException e) {
e.printStackTrace();
}
finish();
}
// Grabbed from http://stackoverflow.com/questions/1656797/how-to-read-a-file-into-string-in-java
private String readFileAsString(String filePath) throws IOException {
StringBuffer fileData = new StringBuffer();
BufferedReader reader = new BufferedReader(
new FileReader(filePath));
char[] buf = new char[1024];
int numRead;
while((numRead=reader.read(buf)) != -1){
String readData = String.valueOf(buf, 0, numRead);
fileData.append(readData);
}
reader.close();
return fileData.toString();
}
// Grabbed from http://stackoverflow.com/questions/1053467/how-do-i-save-a-string-to-a-text-file-using-java
private void writeStringToFile(String filePath, String value) throws IOException {
PrintWriter out = new PrintWriter(filePath);
out.print(value);
out.close();
}
}
Hello everyone I want to put my own textview or edittext in canvas1.java or canvasclass.java . Actually this coding are lipitk toolkit handwriting recognition android application. Please help me if possible.
/************************canvas1.java*********************/
package com.canvas;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.Typeface;
import android.inputmethodservice.InputMethodService;
import android.opengl.Visibility;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Vibrator;
import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnInitListener;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.Display;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.HorizontalScrollView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.Scroller;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.LinearLayout.LayoutParams;
import com.google.tts.TTS;
public class Canvas1 extends Activity implements OnClickListener,OnLongClickListener{
private TTS myTts;
CanvasClass canClass;
private LinearLayout main;
private LinearLayout cenerLayout;
private LinearLayout topLayout;
private LinearLayout subLayout;
private LinearLayout tvLayout;
private LinearLayout SecondLayout;
private LinearLayout mylayout;
private ImageView Exit;
private ScrollView scrllView;
private HorizontalScrollView HorizontalSV;
private TextView[] TV=new TextView[1];
private TextView[] s=new TextView[1];
private TextView[] TViews=new TextView[5];
public final static int mButtonHeight = 220;
public final static int mButtonWidth = 80;
String inst[]=new String[5]; ;
String InstTemp;
int flag=0;
int c0flag=0;
int c1flag=0;
int c2flag=0;
int c3flag=0;
int SpaceSelFlag = 1;
String newStr="";
int height;
public static int width;
Vibrator v;
/** Called when the activity is first created. */
CanvasClass canvasClass = null;
Canvas1 conObj = null;
public final int MY_DATA_CHECK_CODE = 1;
private TextToSpeech mTts = null;
public ProgressDialog dialog;
@override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
width = display.getWidth();
height = display.getHeight();
v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
AssetInstaller assetInstaller = new AssetInstaller(getApplicationContext(), "projects");
try {
assetInstaller.execute();
} catch (IOException e) {
e.printStackTrace();
}
conObj = this;
canvasClass = new CanvasClass(this,conObj);
main = new LinearLayout(this);
main.setOrientation(LinearLayout.VERTICAL);
main.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.FILL_PARENT));
topLayout = new LinearLayout(this);
topLayout.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
((height/2)+130)));
topLayout.setOrientation(LinearLayout.VERTICAL);
topLayout.setBackgroundColor(0xffffffcc);
topLayout.addView(canvasClass);
/*
mylayout = new LinearLayout(this);
mylayout.setOrientation(LinearLayout.VERTICAL);
mylayout.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT));
mylayout.setBackgroundColor(Color.WHITE);
for(int i = 0; i <s.length; i++) {
s = new EditText(this);
s.setTextColor(Color.RED);
s.setTextSize(40);
s.setGravity(Gravity.AXIS_Y_SHIFT);
s.setTypeface(null, Typeface.BOLD);
s.setHeight(height/8);
s.setPadding(5, 0, 0, 0);
s.setScroller(new Scroller(this));
s.setVerticalScrollBarEnabled(true);
s.setMovementMethod(ScrollingMovementMethod.getInstance());
mylayout.addView(s);
}
*/
cenerLayout = new LinearLayout(this);
cenerLayout.setOrientation(LinearLayout.VERTICAL);
cenerLayout.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT));
cenerLayout.setBackgroundColor(Color.GREEN);
for(int i = 0; i <TV.length; i++) {
TV = new TextView(this);
TV.setTextColor(Color.RED);
TV.setTextSize(40);
TV.setGravity(Gravity.CENTER_HORIZONTAL);
TV.setTypeface(null, Typeface.BOLD);
TV.setHeight(height/8);
TV.setPadding(5, 0, 0, 0);
TV.setScroller(new Scroller(this));
TV.setVerticalScrollBarEnabled(true);
TV.setMovementMethod(ScrollingMovementMethod.getInstance());
cenerLayout.addView(TV);
}
SecondLayout = new LinearLayout(this);
SecondLayout.setOrientation(LinearLayout.VERTICAL);
SecondLayout.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
70));
SecondLayout.setBackgroundColor(0xff26466D);
tvLayout = new LinearLayout(this);
tvLayout.setOrientation(LinearLayout.HORIZONTAL);
tvLayout.setLayoutParams(new LinearLayout.LayoutParams(
(width-20),
((height/8)-30)));
for(int i = 0; i < TViews.length; i++) {
TViews = new TextView(this);
TViews.setTextColor(Color.YELLOW);
TViews[0].setText("Suggested words..");
TViews[0].setTextColor(0xffE8E8E8);
TViews.setTextSize(15);
TViews.setGravity(Gravity.CENTER);
TViews.setPadding(10, 0, 0, 0);
TViews.setHeight(((height/8)-30));
TViews.setOnClickListener(this);
tvLayout.addView(TViews);
}
HorizontalSV=new HorizontalScrollView(this);
HorizontalSV.setLayoutParams(new LinearLayout.LayoutParams(
(width-125),
LinearLayout.LayoutParams.WRAP_CONTENT));
HorizontalSV.addView(tvLayout,new LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.FILL_PARENT));
SecondLayout.addView(HorizontalSV);
subLayout = new LinearLayout(this);
subLayout.setOrientation(LinearLayout.HORIZONTAL);
subLayout.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
((height/8)-16)));
subLayout.setGravity(Gravity.BOTTOM);
Exit = new ImageView(this);
Exit.setImageResource(R.drawable.exit);
Exit.setPadding(30, 0, 0, 0);
Exit.setOnClickListener(this);
subLayout.addView(Exit);
main.addView(cenerLayout);
main.addView(topLayout);
main.addView(subLayout);
setContentView(main);
Intent checkIntent = new Intent();
checkIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
startActivityForResult(checkIntent, MY_DATA_CHECK_CODE);
}
protected void onActivityResult(
int requestCode, int resultCode, Intent data) {
if (requestCode == MY_DATA_CHECK_CODE) {
if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
// success, create the TTS instance
mTts = new TextToSpeech(this, new OnInitListener() {
public void onInit(int status) {
// TODO Auto-generated method stub
//mTts.speak("Hello World", TextToSpeech.QUEUE_FLUSH, null);
}
});
} else {
// missing data, install it
Intent installIntent = new Intent();
installIntent.setAction(
TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
startActivity(installIntent);
}
}
}
public void onClick(View v) {
if(v==Exit){
int pid = android.os.Process.myPid();
android.os.Process.killProcess(pid);
}
}
/* This method will handle the swipe across the edge. Calls Freepad once the
touch area reaches the right end of screen */
public void ClearCanvas(){
if(canvasClass != null){
topLayout.removeView(canvasClass);
canvasClass = new CanvasClass(this,conObj);
topLayout.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
((height/2)+130)));
topLayout.addView(canvasClass);
}
}
class ProgressdialogClass extends AsyncTask<Void, Void, String> {
@override
protected String doInBackground(Void... unsued) {
canvasClass.addStroke(canvasClass._currentStroke);
return null;
}
@override
protected void onPostExecute(String sResponse) {
dialog.dismiss();
FreePadCall();
}
@override
protected void onPreExecute(){
dialog = ProgressDialog.show(Canvas1.this, "Processing","Please wait...", true);
}
}
public void CallingMethod(){
ProgressdialogClass ObjAsy=new ProgressdialogClass();
ObjAsy.execute();
}
public void FreePadCall(){
HorizontalSV.setVisibility(View.VISIBLE);
if(canvasClass != null){
topLayout.removeView(canvasClass);
canvasClass.destroyDrawingCache();
canvasClass = new CanvasClass(this,conObj);
topLayout.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
((height/2)+130)));
topLayout.addView(canvasClass);
}
TV[0].setText(canvasClass.character[0]);
String str1 = TV[0].getText().toString();
mTts.speak(str1, 0, null);
}
public boolean onLongClick(View v) {
System.out.println("-----long click------");
return true;
}
int curr_indx = 0;
public void SpeakOutChoices(){
if(canvasClass != null){
topLayout.removeView(canvasClass);
canvasClass = new CanvasClass(this,conObj);
topLayout.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
((height/2)+130)));
topLayout.addView(canvasClass);
}
System.out.println("index"+curr_indx +"---"+ CanvasClass.StrokeResultCount);
if(curr_indx < CanvasClass.StrokeResultCount){
TV[0].setText(CanvasClass.character[curr_indx]);
String Choice1=CanvasClass.character[curr_indx];
mTts.speak(Choice1, 0, null);
curr_indx++;
if(curr_indx == CanvasClass.StrokeResultCount)
curr_indx = 0;
}
}
}
/***************Convasclass.java*******************/
package com.canvas;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import com.canvas.Canvas1.ProgressdialogClass;
import android.R.color;
import android.R.style;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.os.CountDownTimer;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.WindowManager;
import android.view.View;
import android.view.View.OnTouchListener;
public class CanvasClass extends View implements OnTouchListener{
private LipiTKJNIInterface _lipitkInterface;
private LipiTKJNIInterface _recognizer;
private Page _page;
private PointF _lastSpot;
public Stroke _currentStroke;
private ArrayList<PointF> _currentStrokeStore;
private ArrayList<Stroke> _strokes;
private Stroke[] _recognitionStrokes;
private ArrayList<Symbol> _symbols;
public static String[] character;
public static int StrokeResultCount=0;
ArrayList<Values> vals = new ArrayList<Values>();
public static int min=480;
public static int max=0;
public static int minX=800;
public static int maxX=0;
public static int XCood=0;
private int mPosX;
private int mPosY;
private int mLastTouchX=0;
private int mLastTouchY=0;
boolean flag=true;
boolean flagbs=true;
public static boolean canvastest=true;
MyCount counter;
MyLongPressCount myLongPress;
BufferedWriter out;
Canvas1 canObj=null;
private static final String TAG = "DrawView";
public CanvasClass(Context context,Canvas1 canObjParam) {
super(context);
canObj=canObjParam;
globalvariable.paint=new Paint();
setFocusable(true);
setFocusableInTouchMode(true);
this.setOnTouchListener(this);
globalvariable.paint.setColor(Color.BLUE);
globalvariable.paint.setAntiAlias(true);
globalvariable.paint.setDither(true);
globalvariable.paint.setStyle(Paint.Style.STROKE);
globalvariable.paint.setStrokeJoin(Paint.Join.ROUND);
globalvariable.paint.setStrokeCap(Paint.Cap.ROUND);
globalvariable.paint.setStrokeWidth(5);
counter = new MyCount(700,1000);
myLongPress = new MyLongPressCount(3000,1000);
_currentStroke = new Stroke();
_strokes = new ArrayList<Stroke>();
_recognizer = null;
_symbols = new ArrayList<Symbol>();
// Initialize lipitk
Context contextlipi = getContext();
File externalFileDir = contextlipi.getExternalFilesDir(null);
String path = externalFileDir.getPath();
Log.d("JNI", "Path: " + path);
_lipitkInterface = new LipiTKJNIInterface(path, "SHAPEREC_ALPHANUM");
_lipitkInterface.initialize();
_page = new Page(_lipitkInterface);
_recognizer=_lipitkInterface;
}
public boolean onTouch(View view, MotionEvent event) {
Values vs=new Values();
final int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN: {
min=480;
max=0;
maxX=0;
minX=800;
counter.cancel();
myLongPress.start();
globalvariable.IsUserWriting=true;
vs.x = (int) event.getX();
vs.y = (int) event.getY();
float X= (float) vs.x;
float Y= (float) vs.y;
PointF p = new PointF(X, Y);
_lastSpot=p;
_currentStroke.addPoint(p);
if(vs.y>max)
max=vs.y;
if(vs.y<min)
min=vs.y;
if(vs.x>maxX)
maxX=vs.x;
if(vs.x<minX)
minX=vs.x;
XCood=vs.x;
globalvariable.strokeXY += "{" + vs.x + "," + vs.y + "}|";
vals.add(vs);
invalidate();
System.out.println("action down stroke values===");
break;
}
case MotionEvent.ACTION_MOVE: {
counter.cancel();
vs.x = (int) event.getX();
vs.y = (int) event.getY();
float X= (float) vs.x;
float Y= (float) vs.y;
PointF p = new PointF(X, Y);
_lastSpot=p;
_currentStroke.addPoint(p);
//myLongPress.cancel();
globalvariable.VSG=vs.x;
globalvariable.LongPressFlag=true;
globalvariable.strokeXY += "{" + vs.x + "," + vs.y + "}|";
vals.add(vs);
if(vs.y>max)
max=vs.y;
if(vs.y<min)
min=vs.y;
if(vs.x>maxX)
maxX=vs.x;
if(vs.x<minX)
minX=vs.x;
XCood=vs.x;
System.out.println("action move stroke values===");
invalidate();
break;
}
case MotionEvent.ACTION_UP:{
vs.x = (int) event.getX();
vs.y = (int) event.getY();
float X= (float) vs.x;
float Y= (float) vs.y;
PointF p = new PointF(X, Y);
_lastSpot=p;
_currentStroke.addPoint(p);
_currentStrokeStore = new ArrayList<PointF>();
_currentStrokeStore.add(p);
System.out.println("Max==="+max);
System.out.println("Min==="+min);
globalvariable.strokeXY += "N";
/* this condition should be checked only once for the first stroke after
a time out */
if(globalvariable.isFirststroke)
{
if((max-min) < 30 &&(max!=min))
{
globalvariable.IsUserWriting = false;
}
}
if(globalvariable.isFirststroke && globalvariable.IsUserWriting == false)
{
globalvariable.isFirststroke = true;
}
else
{
globalvariable.isFirststroke = false;
}
if(globalvariable.IsUserWriting)
{
counter.start();
}
else
{
if(XCood < 30)
{
//canObj.backspace();
}
else if(XCood > (canObj.width - 30))
{
canObj.SpeakOutChoices();
}
}
myLongPress.cancel();
System.out.println("action up stroke values===");
break;
}
}
return true;
}
public void addStroke(Stroke stroke) {
_strokes.add(stroke);
_recognitionStrokes = new Stroke[_strokes.size()];
for (int s = 0; s < _strokes.size(); s++)
_recognitionStrokes = _strokes.get(s);
LipitkResult[] results = _recognizer.recognize(_recognitionStrokes);
for (LipitkResult result : results) {
Log.e("jni", "ShapeID = " + result.Id + " Confidence = " + result.Confidence);
}
String configFileDirectory = _recognizer.getLipiDirectory() + "/projects/alphanumeric/config/";
character=new String[results.length];
for(int i=0;i<character.length;i++){
character = _recognizer.getSymbolName(results.Id, configFileDirectory);
}
StrokeResultCount=results.length;
_recognitionStrokes = null;
}
public void clearCanvas(){
System.out.println("====inside clearcanvas====");
canvasCpy.drawColor(Color.BLUE);
System.out.println("====over clearcanvas====");
}
public static Canvas canvasCpy = null;
int canvasWidth = 0;
int canvasHeight = 0;
private Bitmap bitmap;
@override
protected void onDraw(Canvas canvas) {
canvasHeight=canvas.getHeight();
canvasWidth=canvas.getWidth();
for (Values values : vals) {
canvas.save();
canvas.drawPoint(values.x, values.y, globalvariable.paint);
canvas.restore();
mLastTouchX=values.x;
mLastTouchY=values.y;
}
File root = android.os.Environment.getExternalStorageDirectory();
File file = new File(root, "Freepad/points.txt");
if(!(file.isDirectory()))
{
return;
}
else
{
try {
out = new BufferedWriter(new FileWriter(file));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
out.write(globalvariable.strokeXY);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
out.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
globalvariable.canvasvar=canvas;
System.out.println("stroke values:-------"+globalvariable.strokeXY);
System.out.println("stroke values:-------"+globalvariable.strokeXY.length());
}
}
public class MyCount extends CountDownTimer{
public MyCount(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
@override
public void onFinish() {
System.out.println("Timer Flag :: " + globalvariable.TimerFlag);
if(globalvariable.LongPressFlag){
canObj.CallingMethod();
globalvariable.IsUserWriting=false;
globalvariable.isFirststroke = true;
}
else{
}
}
@override
public void onTick(long millisUntilFinished) {
System.out.println("Tick tick Flag :: " + globalvariable.TimerFlag);
}
}
public class MyLongPressCount extends CountDownTimer{
public MyLongPressCount(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
@override
public void onFinish() {
globalvariable.LongPressFlag=false;
System.out.println("Long press timer expiry: Timer Flag :: " + globalvariable.TimerFlag);
canObj.ClearCanvas();
}
@override
public void onTick(long millisUntilFinished) {
System.out.println("Tick tick Flag :: " + globalvariable.TimerFlag);
}
}
}
class Values {
int x, y;
@override
public String toString() {
return x + ", " + y;
}
}
Introduction
Site Kit is basically used for apps to provide the place related services. This kit provide to search the places with keyword, Find nearby place, place suggestion for user input, Get place details using the unique id.
Features of Huawei Site Kit
Keyword search: Returns a place list based on keywords entered by the user.
Nearby place search: Searches for nearby places based on the current location of the user's device.
Place details: Searches for details about a place.
Search suggestion: Returns a list of place suggestions.
Site Search: Returns a site object.
Development Overview
You need to install Android Studio IDE and I assume that you have prior knowledge of Android application development.
Hardware Requirements
A computer (desktop or laptop) running Windows 10.
Android phone (with the USB cable), which is used for debugging.
Software Requirements
Java JDK 1.8 or later.
Android Studio software or Visual Studio or Code installed.
HMS Core (APK) 4.X or later
Integration steps
Step 1. Huawei developer account and complete identity verification in Huawei developer website, refer to register Huawei ID.
Step 2. Create project in AppGallery Connect
Step 3. Adding HMS Core SDK
Let's start coding
MainActivity.kt
Java:
package com.huawei.hms.knowmyboard.dtse.activity.view
import androidx.navigation.Navigation.findNavController
import androidx.navigation.ui.NavigationUI.setupWithNavController
import com.huawei.hms.knowmyboard.dtse.activity.viewmodel.LoginViewModel
import android.graphics.Bitmap
import com.huawei.hms.mlsdk.langdetect.local.MLLocalLangDetector
import com.huawei.hms.mlsdk.translate.local.MLLocalTranslator
import android.app.ProgressDialog
import androidx.navigation.NavController
import android.os.Bundle
import androidx.databinding.DataBindingUtil
import com.huawei.hms.knowmyboard.dtse.activity.app.MyApplication
import android.content.Intent
import com.huawei.hms.support.account.AccountAuthManager
import android.provider.MediaStore
import com.huawei.hmf.tasks.OnSuccessListener
import com.huawei.hms.mlsdk.langdetect.MLLangDetectorFactory
import com.huawei.hms.mlsdk.langdetect.local.MLLocalLangDetectorSetting
import com.huawei.hmf.tasks.OnFailureListener
import android.content.DialogInterface
import android.net.Uri
import android.util.Log
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.ViewModelProvider
import com.google.android.material.bottomnavigation.BottomNavigationView
import com.huawei.hms.common.ApiException
import com.huawei.hms.knowmyboard.dtse.R
import com.huawei.hms.knowmyboard.dtse.activity.model.UserData
import com.huawei.hms.knowmyboard.dtse.activity.util.Constants
import com.huawei.hms.knowmyboard.dtse.databinding.ActivityMainBinding
import com.huawei.hms.mlsdk.MLAnalyzerFactory
import com.huawei.hms.mlsdk.common.MLApplication
import com.huawei.hms.mlsdk.common.MLFrame
import com.huawei.hms.mlsdk.translate.local.MLLocalTranslateSetting
import com.huawei.hms.mlsdk.translate.MLTranslatorFactory
import com.huawei.hms.mlsdk.model.download.MLModelDownloadStrategy
import com.huawei.hms.mlsdk.model.download.MLModelDownloadListener
import com.huawei.hms.mlsdk.text.MLLocalTextSetting
import com.huawei.hms.mlsdk.text.MLText
import com.huawei.hms.mlsdk.text.MLTextAnalyzer
import java.io.IOException
import java.lang.Exception
import java.util.ArrayList
class MainActivity() : AppCompatActivity() {
var loginViewModel: LoginViewModel? = null
private var mTextAnalyzer: MLTextAnalyzer? = null
var imagePath: Uri? = null
var bitmap: Bitmap? = null
var result = ArrayList<String>()
var myLocalLangDetector: MLLocalLangDetector? = null
var myLocalTranslator: MLLocalTranslator? = null
var textRecognized: String? = null
var progressDialog: ProgressDialog? = null
var navController: NavController? = null
var activityMainBinding: ActivityMainBinding? = null
var bottomNavigationView: BottomNavigationView? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activityMainBinding =
DataBindingUtil.setContentView([email protected], R.layout.activity_main)
loginViewModel = ViewModelProvider([email protected]).get(
LoginViewModel::class.java
)
navController = findNavController([email protected], R.id.nav_host_fragment)
MyApplication.activity = this
progressDialog = ProgressDialog(this)
progressDialog!!.setCancelable(false)
bottomNavigationView = activityMainBinding!!.bottomNavigation
setupWithNavController(bottomNavigationView!!, navController!!)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
// Process the authorization result to obtain the authorization code from AuthAccount.
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == 1234) {
Log.e("TAG", " Result can be pulled")
}
if (requestCode == 8888) {
val authAccountTask = AccountAuthManager.parseAuthResultFromIntent(data)
if (authAccountTask.isSuccessful) {
// The sign-in is successful, and the user's ID information and authorization code are obtained.
val authAccount = authAccountTask.result
val userData = UserData()
userData.accessToken = authAccount.accessToken
userData.countryCode = authAccount.countryCode
userData.displayName = authAccount.displayName
userData.email = authAccount.email
userData.familyName = authAccount.familyName
userData.givenName = authAccount.givenName
userData.idToken = authAccount.idToken
userData.openId = authAccount.openId
userData.uid = authAccount.uid
userData.photoUriString = authAccount.avatarUri.toString()
userData.unionId = authAccount.unionId
loginViewModel = ViewModelProvider([email protected]).get(
LoginViewModel::class.java
)
loginViewModel!!.sendData(authAccount.displayName)
} else {
// The sign-in failed.
Log.e(
"TAG",
"sign in failed:" + (authAccountTask.exception as ApiException).statusCode
)
}
}
if ((requestCode == 2323) && (resultCode == RESULT_OK) && (data != null)) {
progressDialog!!.setMessage("Initializing text detection..")
progressDialog!!.show()
imagePath = data.data
try {
bitmap = MediaStore.Images.Media.getBitmap(this.contentResolver, imagePath)
asyncAnalyzeText(bitmap)
} catch (e: IOException) {
e.printStackTrace()
Log.e("TAG", " BITMAP ERROR")
}
}
if ((requestCode == 2424) && (resultCode == RESULT_OK) && (data != null)) {
progressDialog!!.setMessage("Initializing text detection..")
progressDialog!!.show()
try {
bitmap = data.extras!!["data"] as Bitmap?
asyncAnalyzeText(bitmap)
} catch (e: Exception) {
e.printStackTrace()
Log.e("TAG", " BITMAP ERROR")
}
}
}
private fun asyncAnalyzeText(bitmap: Bitmap?) {
if (mTextAnalyzer == null) {
createMLTextAnalyzer()
}
val frame = MLFrame.fromBitmap(bitmap)
val task = mTextAnalyzer!!.asyncAnalyseFrame(frame)
task.addOnSuccessListener(object : OnSuccessListener<MLText> {
override fun onSuccess(text: MLText) {
progressDialog!!.setMessage("Initializing language detection..")
textRecognized = text.stringValue.trim { it <= ' ' }
if (!textRecognized!!.isEmpty()) {
// Create a local language detector.
val factory = MLLangDetectorFactory.getInstance()
val setting =
MLLocalLangDetectorSetting.Factory() // Set the minimum confidence threshold for language detection.
.setTrustedThreshold(0.01f)
.create()
myLocalLangDetector = factory.getLocalLangDetector(setting)
val firstBestDetectTask = myLocalLangDetector!!.firstBestDetect(textRecognized)
firstBestDetectTask.addOnSuccessListener(OnSuccessListener { languageDetected ->
progressDialog!!.setMessage("Initializing text translation..")
// Processing logic for detection success.
textTranslate(languageDetected, textRecognized!!, bitmap)
}).addOnFailureListener(object : OnFailureListener {
override fun onFailure(e: Exception) {
// Processing logic for detection failure.
Log.e("TAG", "Lang detect error:" + e.message)
}
})
} else {
progressDialog!!.dismiss()
showErrorDialog("Failed to recognize text.")
}
}
}).addOnFailureListener(object : OnFailureListener {
override fun onFailure(e: Exception) {
Log.e("TAG", "#==>" + e.message)
}
})
}
private fun showErrorDialog(msg: String) {
val alertDialog = AlertDialog.Builder(this).create()
alertDialog.setTitle("Error")
alertDialog.setMessage(msg)
alertDialog.setButton(
AlertDialog.BUTTON_POSITIVE,
"OK",
object : DialogInterface.OnClickListener {
override fun onClick(dialog: DialogInterface, which: Int) {
dialog.dismiss()
}
})
alertDialog.show()
}
private fun textTranslate(languageDetected: String, textRecognized: String, uri: Bitmap?) {
MLApplication.initialize(application)
MLApplication.getInstance().apiKey = Constants.API_KEY
// Create an offline translator.
val setting =
MLLocalTranslateSetting.Factory() // Set the source language code. The ISO 639-1 standard is used. This parameter is mandatory. If this parameter is not set, an error may occur.
.setSourceLangCode(languageDetected) // Set the target language code. The ISO 639-1 standard is used. This parameter is mandatory. If this parameter is not set, an error may occur.
.setTargetLangCode("en")
.create()
myLocalTranslator = MLTranslatorFactory.getInstance().getLocalTranslator(setting)
// Set the model download policy.
val downloadStrategy = MLModelDownloadStrategy.Factory()
.needWifi() // It is recommended that you download the package in a Wi-Fi environment.
.create()
// Create a download progress listener.
val modelDownloadListener: MLModelDownloadListener = object : MLModelDownloadListener {
override fun onProcess(alreadyDownLength: Long, totalLength: Long) {
runOnUiThread(object : Runnable {
override fun run() {
// Display the download progress or perform other operations.
}
})
}
}
myLocalTranslator!!.preparedModel(downloadStrategy, modelDownloadListener)
.addOnSuccessListener(object : OnSuccessListener<Void?> {
override fun onSuccess(aVoid: Void?) {
// Called when the model package is successfully downloaded.
// input is a string of less than 5000 characters.
val task = myLocalTranslator!!.asyncTranslate(textRecognized)
// Before translation, ensure that the models have been successfully downloaded.
task.addOnSuccessListener(object : OnSuccessListener<String> {
override fun onSuccess(translated: String) {
// Processing logic for detection success.
result.clear()
result.add(languageDetected.trim { it <= ' ' })
result.add(textRecognized.trim { it <= ' ' })
result.add(translated.trim { it <= ' ' })
loginViewModel!!.setImage(uri!!)
loginViewModel!!.setTextRecongnized(result)
progressDialog!!.dismiss()
}
}).addOnFailureListener(object : OnFailureListener {
override fun onFailure(e: Exception) {
// Processing logic for detection failure.
progressDialog!!.dismiss()
}
})
}
}).addOnFailureListener(object : OnFailureListener {
override fun onFailure(e: Exception) {
// Called when the model package fails to be downloaded.
progressDialog!!.dismiss()
}
})
}
private fun createMLTextAnalyzer() {
val setting = MLLocalTextSetting.Factory()
.setOCRMode(MLLocalTextSetting.OCR_DETECT_MODE)
.create()
mTextAnalyzer = MLAnalyzerFactory.getInstance().getLocalTextAnalyzer(setting)
}
override fun onStop() {
if (myLocalLangDetector != null) {
myLocalLangDetector!!.stop()
}
if (myLocalTranslator != null) {
myLocalTranslator!!.stop()
}
if (progressDialog != null) {
progressDialog!!.dismiss()
}
super.onStop()
}
companion object {
var TAG = "TAG"
}
}
LoginViewModel.kt
Java:
package com.huawei.hms.knowmyboard.dtse.activity.viewmodel
import android.app.Application
import com.huawei.hms.support.account.service.AccountAuthService
import android.graphics.Bitmap
import com.huawei.hms.location.LocationResult
import com.huawei.hms.site.api.model.Site
import android.widget.Toast
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.huawei.hms.common.ApiException
import com.huawei.hms.knowmyboard.dtse.R
import com.huawei.hms.support.account.request.AccountAuthParams
import com.huawei.hms.support.account.request.AccountAuthParamsHelper
import com.huawei.hms.support.account.AccountAuthManager
import com.huawei.hms.knowmyboard.dtse.activity.app.MyApplication
import java.util.ArrayList
class LoginViewModel(application: Application) : AndroidViewModel(application) {
var service: AccountAuthService? = null
val message = MutableLiveData<String>()
val textRecongnized = MutableLiveData<ArrayList<String>>()
val imagePath = MutableLiveData<Bitmap>()
val locationResult = MutableLiveData<LocationResult>()
val siteSelected = MutableLiveData<Site>()
fun getSiteSelected(): LiveData<Site> {
return siteSelected
}
fun setSiteSelected(siteSelected: Site) {
this.siteSelected.value = siteSelected
}
fun sendData(msg: String) {
message.value = msg
}
fun getMessage(): LiveData<String> {
return message
}
fun setImage(imagePath: Bitmap) {
this.imagePath.value = imagePath
}
fun setLocationResult(locationResult: LocationResult) {
this.locationResult.value = locationResult
}
fun setTextRecongnized(textRecongnized: ArrayList<String>) {
this.textRecongnized.value = textRecongnized
}
fun logoutHuaweiID() {
if (service != null) {
service!!.signOut()
sendData("KnowMyBoard")
Toast.makeText(getApplication(), "You are logged out from Huawei ID", Toast.LENGTH_LONG)
.show()
}
}
fun loginClicked() {
val authParams =
AccountAuthParamsHelper(AccountAuthParams.DEFAULT_AUTH_REQUEST_PARAM).setAuthorizationCode()
.createParams()
service = AccountAuthManager.getService(MyApplication.activity, authParams)
MyApplication.activity!!.startActivityForResult(service!!.signInIntent, 8888)
}
fun cancelAuthorization() {
if (service != null) {
// service indicates the AccountAuthService instance generated using the getService method during the sign-in authorization.
service!!.cancelAuthorization().addOnCompleteListener { task ->
if (task.isSuccessful) {
// Processing after a successful authorization cancellation.
sendData(getApplication<Application>().resources.getResourceName(R.string.app_name))
Toast.makeText(getApplication(), "Cancelled authorization", Toast.LENGTH_LONG)
.show()
} else {
// Handle the exception.
val exception = task.exception
if (exception is ApiException) {
val statusCode = exception.statusCode
Toast.makeText(
getApplication(),
"Failed to cancel authorization. status code $statusCode",
Toast.LENGTH_LONG
).show()
}
}
}
} else {
Toast.makeText(getApplication(), "Login required", Toast.LENGTH_LONG).show()
}
}
}
SearchFragment.kt
Java:
package com.huawei.hms.knowmyboard.dtse.activity.fragments
import androidx.navigation.Navigation.findNavController
import com.huawei.hms.knowmyboard.dtse.activity.viewmodel.LoginViewModel
import androidx.navigation.NavController
import com.huawei.hms.site.api.SearchService
import com.huawei.hms.knowmyboard.dtse.activity.adapter.SitesAdapter
import com.huawei.hms.site.api.model.Site
import com.huawei.hms.location.LocationResult
import com.huawei.hms.knowmyboard.dtse.activity.intefaces.ItemClickListener
import android.view.WindowManager
import android.view.LayoutInflater
import android.view.ViewGroup
import android.os.Bundle
import android.util.Log
import android.view.View
import androidx.appcompat.widget.SearchView
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.huawei.hms.knowmyboard.dtse.R
import com.huawei.hms.knowmyboard.dtse.activity.util.Constants
import com.huawei.hms.knowmyboard.dtse.databinding.FragmentSearchBinding
import com.huawei.hms.site.api.SearchServiceFactory
import com.huawei.hms.site.api.model.TextSearchRequest
import com.huawei.hms.site.api.model.Coordinate
import com.huawei.hms.site.api.SearchResultListener
import com.huawei.hms.site.api.model.TextSearchResponse
import com.huawei.hms.site.api.model.SearchStatus
import com.huawei.hms.site.api.model.NearbySearchRequest
import com.huawei.hms.site.api.model.HwLocationType
import com.huawei.hms.site.api.model.NearbySearchResponse
import java.io.UnsupportedEncodingException
import java.lang.Exception
import java.net.URLEncoder
import java.util.ArrayList
class SearchFragment : Fragment() {
var binding: FragmentSearchBinding? = null
var loginViewModel: LoginViewModel? = null
//View view;
var navController: NavController? = null
private var searchService: SearchService? = null
var adapter: SitesAdapter? = null
var siteArrayList = ArrayList<Site>()
var locationResult: LocationResult? = null
/* var siteClicklistener = ItemClickListener { vh, site, pos ->
requireActivity().window.setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN
)
loginViewModel!!.setSiteSelected(site)
navController!!.navigate(R.id.loginFragment)
}*/
var siteClicklistener = object : ItemClickListener{
override fun onItemClicked(vh: RecyclerView.ViewHolder?, item: Site?, pos: Int) {
requireActivity().window.setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN
)
loginViewModel!!.setSiteSelected(item!!)
navController!!.navigate(R.id.loginFragment)
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
requireActivity().window.setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE
)
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_search, container, false)
loginViewModel = ViewModelProvider(requireActivity()).get(
LoginViewModel::class.java
)
val searchView = binding!!.edSearch
val recyclerView = binding!!.suggestionRv
navController = findNavController(requireActivity(), R.id.nav_host_fragment)
searchView.isFocusable = true
searchView.onActionViewExpanded()
adapter = SitesAdapter(siteArrayList, context, siteClicklistener)
recyclerView.adapter = adapter
recyclerView.layoutManager = LinearLayoutManager(context)
recyclerView.setHasFixedSize(true)
loginViewModel!!.locationResult.observeForever { locationResult1 ->
locationResult = locationResult1
}
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String): Boolean {
return false
}
override fun onQueryTextChange(newText: String): Boolean {
if (newText.length > 4) {
nearByPlacesSearch(newText)
}
return false
}
})
return binding!!.root
}
fun keywordSearch(search: String?) {
try {
val key = URLEncoder.encode(Constants.API_KEY, "UTF-8")
// Instantiate the SearchService object.
searchService = SearchServiceFactory.create(context, key)
// Create a request body.
val request = TextSearchRequest()
request.query = search
if (locationResult != null) {
val location = Coordinate(
locationResult!!.lastHWLocation.latitude,
locationResult!!.lastHWLocation.longitude
)
request.location = location
}
request.radius = 1000
//request.setHwPoiType(HwLocationType.HOTEL_MOTEL);
request.countryCode = "IN"
request.language = "en"
request.pageIndex = 1
request.pageSize = 5
request.isChildren = false
// request.setCountries(Arrays.asList("en", "fr", "cn", "de", "ko","in"));
// Create a search result listener.
val resultListener: SearchResultListener<TextSearchResponse?> =
object : SearchResultListener<TextSearchResponse?> {
// Return search results upon a successful search.
override fun onSearchResult(results: TextSearchResponse?) {
if (results == null || results.totalCount <= 0) {
return
}
val sites = results.sites
if (sites == null || sites.size == 0) {
return
}
siteArrayList.clear()
for (site in sites) {
siteArrayList.add(site)
}
siteArrayList.addAll(sites)
adapter!!.notifyDataSetChanged()
}
// Return the result code and description upon a search exception.
override fun onSearchError(status: SearchStatus) {
Log.i("TAG", "Error : " + status.errorCode + " " + status.errorMessage)
}
}
// Call the keyword search API.
searchService!!.textSearch(request, resultListener)
} catch (e: UnsupportedEncodingException) {
e.printStackTrace()
}
}
fun nearByPlacesSearch(newText: String?) {
try {
val key = URLEncoder.encode(Constants.API_KEY, "UTF-8")
// Instantiate the SearchService object.
searchService = SearchServiceFactory.create(context, key)
// Create a request body.
val request = NearbySearchRequest()
if (locationResult != null) {
val location = Coordinate(
locationResult!!.lastHWLocation.latitude,
locationResult!!.lastHWLocation.longitude
)
request.location = location
}
request.query = newText
request.radius = 1000
request.hwPoiType = HwLocationType.ADDRESS
request.language = "en"
request.pageIndex = 1
request.pageSize = 5
request.strictBounds = false
// Create a search result listener.
val resultListener: SearchResultListener<NearbySearchResponse?> =
object : SearchResultListener<NearbySearchResponse?> {
// Return search results upon a successful search.
override fun onSearchResult(results: NearbySearchResponse?) {
if (results == null || results.totalCount <= 0) {
return
}
val sites = results.sites
if (sites == null || sites.size == 0) {
return
}
siteArrayList.clear()
for (site in sites) {
siteArrayList.add(site)
}
siteArrayList.addAll(sites)
adapter!!.notifyDataSetChanged()
}
// Return the result code and description upon a search exception.
override fun onSearchError(status: SearchStatus) {
Log.i("TAG", "Error : " + status.errorCode + " " + status.errorMessage)
}
}
// Call the nearby place search API.
searchService!!.nearbySearch(request, resultListener)
} catch (e: Exception) {
e.printStackTrace()
}
}
}
RequestLocationData.kt
Java:
package com.huawei.hms.knowmyboard.dtse.activity.util
import android.Manifest
import com.huawei.hms.knowmyboard.dtse.activity.viewmodel.LoginViewModel
import android.app.Activity
import android.content.Context
import android.os.Build
import android.content.pm.PackageManager
import android.os.Looper
import android.location.Geocoder
import android.util.Log
import androidx.annotation.RequiresApi
import androidx.core.app.ActivityCompat
import androidx.fragment.app.FragmentActivity
import com.huawei.hms.location.*
import java.io.IOException
import java.lang.StringBuilder
import java.util.*
class RequestLocationData(
context: Context?,
activity: FragmentActivity?,
loginViewModel: LoginViewModel?
) {
private var settingsClient: SettingsClient? = null
private var isLocationSettingSuccess = 0
private var myLocationRequest: LocationRequest? = null
// Define a fusedLocationProviderClient object.
private var fusedLocationProviderClient: FusedLocationProviderClient? = null
private var myLocationCallback: LocationCallback? = null
var context: Context? = null
var activity: Activity? = null
private var locationResult: LocationResult? = null
var loginViewModel: LoginViewModel? = null
fun initFusionLocationProviderClint() {
// Instantiate the fusedLocationProviderClient object.
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(activity)
this.settingsClient = LocationServices.getSettingsClient(activity)
}
fun checkDeviceLocationSettings() {
val builder = LocationSettingsRequest.Builder()
myLocationRequest = LocationRequest()
builder.addLocationRequest(myLocationRequest)
val locationSettingsRequest = builder.build()
// Check the device location settings.
settingsClient!!.checkLocationSettings(locationSettingsRequest) // Define the listener for success in calling the API for checking device location settings.
.addOnSuccessListener { locationSettingsResponse: LocationSettingsResponse ->
val locationSettingsStates = locationSettingsResponse.locationSettingsStates
val stringBuilder = StringBuilder()
// Check whether the location function is enabled.
stringBuilder.append(",\nisLocationUsable=")
.append(locationSettingsStates.isLocationUsable)
// Check whether HMS Core (APK) is available.
stringBuilder.append(",\nisHMSLocationUsable=")
.append(locationSettingsStates.isHMSLocationUsable)
Log.i(TAG, "checkLocationSetting onComplete:$stringBuilder")
// Set the location type.
myLocationRequest!!.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
// Set the number of location updates to 1.
myLocationRequest!!.numUpdates = 1
isLocationSettingSuccess = 1
} // Define callback for failure in checking the device location settings.
.addOnFailureListener { e -> Log.i(TAG, "checkLocationSetting onFailure:" + e.message) }
}
@RequiresApi(Build.VERSION_CODES.S)
fun checkPermission() {
// Dynamically apply for required permissions if the API level is 28 or lower.
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
Log.i(TAG, "android sdk <= 28 Q")
if (ActivityCompat.checkSelfPermission(
context!!,
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(
context!!,
Manifest.permission.ACCESS_COARSE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
val strings = arrayOf(
Manifest.permission.CAMERA,
Manifest.permission.MANAGE_MEDIA,
Manifest.permission.MEDIA_CONTENT_CONTROL,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
)
ActivityCompat.requestPermissions(activity!!, strings, 1)
}
} else {
// Dynamically apply for the android.permission.ACCESS_BACKGROUND_LOCATION permission in addition to the preceding permissions if the API level is higher than 28.
if (ActivityCompat.checkSelfPermission(
activity!!,
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
context!!,
Manifest.permission.ACCESS_COARSE_LOCATION
) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
context!!,
"android.permission.ACCESS_BACKGROUND_LOCATION"
) != PackageManager.PERMISSION_GRANTED
) {
val strings = arrayOf(
Manifest.permission.CAMERA,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.MEDIA_CONTENT_CONTROL,
Manifest.permission.MANAGE_MEDIA,
"android.permission.ACCESS_BACKGROUND_LOCATION"
)
ActivityCompat.requestPermissions(activity!!, strings, 2)
}
}
}
fun refreshLocation(): LocationResult? {
Log.d(TAG, "Refreshing location")
if (isLocationSettingSuccess == 1) {
myLocationCallback = object : LocationCallback() {
private var locationResult: LocationResult? = null
override fun onLocationResult(locationResult: LocationResult) {
if (locationResult != null) {
// Gson gson = new Gson();
//Log.d(TAG, " Location data :" + locationResult.getLastLocation().getLatitude() + " : " + locationResult.getLastLocation().getLongitude());
//Log.d(TAG, " Location data :" + gson.toJson(locationResult.getLastHWLocation()));
//Log.d(TAG, " Location data :" + locationResult.getLastHWLocation().getCountryName());
Log.d(TAG, " Location data :" + locationResult.lastHWLocation.latitude)
Log.d(TAG, " Location data :" + locationResult.lastHWLocation.longitude)
// binding.textDetected.setText("Latitude " + locationResult.getLastHWLocation().getLatitude() + " Longitude " + locationResult.getLastHWLocation().getLongitude());
//getGeoCoderValues(locationResult.getLastHWLocation().getLatitude(),locationResult.getLastHWLocation().getLongitude());
this.locationResult = locationResult
loginViewModel!!.setLocationResult(locationResult)
}
}
}
fusedLocationProviderClient!!.requestLocationUpdates(
myLocationRequest,
myLocationCallback,
Looper.getMainLooper()
)
} else {
Log.d(TAG, "Failed to get location settings")
}
return locationResult
}
fun disableLocationData() {
fusedLocationProviderClient!!.disableBackgroundLocation()
fusedLocationProviderClient!!.removeLocationUpdates(myLocationCallback)
}
private fun getGeoCoderValues(latitude: Double, longitude: Double) {
getAddress(context, latitude, longitude)
/* Geocoder geocoder;
List<Address> addresses;
Locale locale = new Locale("en", "IN");
geocoder = new Geocoder(getContext(), locale);
try {
addresses = geocoder.getFromLocation(latitude, longitude, 1); // Here 1 represent max location result to returned, by documents it recommended 1 to 5
Gson gson=new Gson();
Log.d(TAG,"Geo coder :"+gson.toJson(addresses));
String address = addresses.get(0).getAddressLine(0); // If any additional address line present than only, check with max available address lines by getMaxAddressLineIndex()
String city = addresses.get(0).getLocality();
String state = addresses.get(0).getAdminArea();
String country = addresses.get(0).getCountryName();
String postalCode = addresses.get(0).getPostalCode();
String knownName = addresses.get(0).getFeatureName();
} catch (IOException e) {
e.printStackTrace();
Log.e(TAG,"Error while fetching Geo coder :"+e.getMessage());
}*/
/* Locale locale = new Locale("en", "IN");
GeocoderService geocoderService =
LocationServices.getGeocoderService(getActivity().getBaseContext(), locale);
// Request reverse geocoding.
GetFromLocationRequest getFromLocationRequest = new GetFromLocationRequest(latitude, longitude, 5);
// Initiate reverse geocoding.
geocoderService.getFromLocation(getFromLocationRequest)
.addOnSuccessListener(hwLocation -> {
Gson gson=new Gson();
Log.d(TAG,"Geo coder :"+gson.toJson(hwLocation));
})
.addOnFailureListener(e -> {
Log.e(TAG,"Error while fetching Geo coder :"+e.getMessage());
});*/
}
companion object {
var TAG = "TAG"
fun getAddress(context: Context?, LATITUDE: Double, LONGITUDE: Double) {
//Set Address
try {
val geocoder = Geocoder(context, Locale.getDefault())
val addresses = geocoder.getFromLocation(LATITUDE, LONGITUDE, 1)
if (addresses != null && addresses.size > 0) {
val address =
addresses[0].getAddressLine(0) // If any additional address line present than only, check with max available address lines by getMaxAddressLineIndex()
val city = addresses[0].locality
val state = addresses[0].adminArea
val country = addresses[0].countryName
val postalCode = addresses[0].postalCode
val knownName = addresses[0].featureName // Only if available else return NULL
Log.d(TAG, "getAddress: address$address")
Log.d(TAG, "getAddress: city$city")
Log.d(TAG, "getAddress: state$state")
Log.d(TAG, "getAddress: postalCode$postalCode")
Log.d(TAG, "getAddress: knownName$knownName")
}
} catch (e: IOException) {
e.printStackTrace()
Log.e(TAG, "Error while fetching Geo coder :" + e.message)
}
}
}
init {
[email protected] = context
[email protected] = activity
[email protected] = loginViewModel
}
}
navigation_graph.xml
XML:
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/navigation_graph"
app:startDestination="@id/loginFragment">
<fragment
android:id="@+id/loginFragment"
android:name="com.huawei.hms.knowmyboard.dtse.activity.fragments.LoginFragment"
android:label="LoginFragment"/>
<fragment
android:id="@+id/mainFragment"
android:name="com.huawei.hms.knowmyboard.dtse.activity.fragments.MainFragment"
android:label="MainFragment"/>
<fragment
android:id="@+id/searchFragment"
android:name="com.huawei.hms.knowmyboard.dtse.activity.fragments.SearchFragment"
android:label="fragment_search"
tools:layout="@layout/fragment_search" />
</navigation>
bottom_navigation_menu.xml
XML:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/searchFragment"
android:icon="@android:drawable/ic_menu_search"
android:title="@string/search" />
<item
android:id="@+id/loginFragment"
android:icon="@android:drawable/ic_menu_agenda"
android:title="Home" />
<item
android:id="@+id/mainFragment"
app:showAsAction="always"
android:icon="@android:drawable/ic_menu_gallery"
android:title="Gallery" />
</menu>
Result
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
Tricks and Tips
Makes sure that agconnect-services.json file added.
Make sure required dependencies are added
Make sure that service is enabled in AGC
Enable data binding in gradle.build file
Make sure bottom navigation id's should be same as fragment id's in navigation graph
Conclusion
In this article, we have learnt how to integrate Huawei Site Kit, Map kit, Location kit in Android application KnowMyBoard. Hoping that the Map kit capabilities are helpful to you as well, like this sample, you can make use of Site kit as per your requirement.
Reference
Map Kit – Training video
Site Kit – Training video
Introduction
Site Kit is basically used for apps to provide the place related services. This kit provide to search the places with keyword, Find nearby place, place suggestion for user input, Get place details using the unique id.
Features of Huawei Site Kit
Keyword search: Returns a place list based on keywords entered by the user.
Nearby place search: Searches for nearby places based on the current location of the user's device.
Place details: Searches for details about a place.
Search suggestion: Returns a list of place suggestions.
Site Search: Returns a site object.
Development Overview
You need to install Android Studio IDE and I assume that you have prior knowledge of Android application development.
Hardware Requirements
A computer (desktop or laptop) running Windows 10.
Android phone (with the USB cable), which is used for debugging.
Software Requirements
Java JDK 1.8 or later.
Android Studio software or Visual Studio or Code installed.
HMS Core (APK) 4.X or later
Integration steps
Step 1. Huawei developer account and complete identity verification in Huawei developer website, refer to register Huawei ID.
Step 2. Create project in AppGallery Connect
Step 3. Adding HMS Core SDK
Let's start coding
MainActivity.kt
Java:
package com.huawei.hms.knowmyboard.dtse.activity.view
import androidx.navigation.Navigation.findNavController
import androidx.navigation.ui.NavigationUI.setupWithNavController
import com.huawei.hms.knowmyboard.dtse.activity.viewmodel.LoginViewModel
import android.graphics.Bitmap
import com.huawei.hms.mlsdk.langdetect.local.MLLocalLangDetector
import com.huawei.hms.mlsdk.translate.local.MLLocalTranslator
import android.app.ProgressDialog
import androidx.navigation.NavController
import android.os.Bundle
import androidx.databinding.DataBindingUtil
import com.huawei.hms.knowmyboard.dtse.activity.app.MyApplication
import android.content.Intent
import com.huawei.hms.support.account.AccountAuthManager
import android.provider.MediaStore
import com.huawei.hmf.tasks.OnSuccessListener
import com.huawei.hms.mlsdk.langdetect.MLLangDetectorFactory
import com.huawei.hms.mlsdk.langdetect.local.MLLocalLangDetectorSetting
import com.huawei.hmf.tasks.OnFailureListener
import android.content.DialogInterface
import android.net.Uri
import android.util.Log
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.ViewModelProvider
import com.google.android.material.bottomnavigation.BottomNavigationView
import com.huawei.hms.common.ApiException
import com.huawei.hms.knowmyboard.dtse.R
import com.huawei.hms.knowmyboard.dtse.activity.model.UserData
import com.huawei.hms.knowmyboard.dtse.activity.util.Constants
import com.huawei.hms.knowmyboard.dtse.databinding.ActivityMainBinding
import com.huawei.hms.mlsdk.MLAnalyzerFactory
import com.huawei.hms.mlsdk.common.MLApplication
import com.huawei.hms.mlsdk.common.MLFrame
import com.huawei.hms.mlsdk.translate.local.MLLocalTranslateSetting
import com.huawei.hms.mlsdk.translate.MLTranslatorFactory
import com.huawei.hms.mlsdk.model.download.MLModelDownloadStrategy
import com.huawei.hms.mlsdk.model.download.MLModelDownloadListener
import com.huawei.hms.mlsdk.text.MLLocalTextSetting
import com.huawei.hms.mlsdk.text.MLText
import com.huawei.hms.mlsdk.text.MLTextAnalyzer
import java.io.IOException
import java.lang.Exception
import java.util.ArrayList
class MainActivity() : AppCompatActivity() {
var loginViewModel: LoginViewModel? = null
private var mTextAnalyzer: MLTextAnalyzer? = null
var imagePath: Uri? = null
var bitmap: Bitmap? = null
var result = ArrayList<String>()
var myLocalLangDetector: MLLocalLangDetector? = null
var myLocalTranslator: MLLocalTranslator? = null
var textRecognized: String? = null
var progressDialog: ProgressDialog? = null
var navController: NavController? = null
var activityMainBinding: ActivityMainBinding? = null
var bottomNavigationView: BottomNavigationView? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activityMainBinding =
DataBindingUtil.setContentView([email protected], R.layout.activity_main)
loginViewModel = ViewModelProvider([email protected]).get(
LoginViewModel::class.java
)
navController = findNavController([email protected], R.id.nav_host_fragment)
MyApplication.activity = this
progressDialog = ProgressDialog(this)
progressDialog!!.setCancelable(false)
bottomNavigationView = activityMainBinding!!.bottomNavigation
setupWithNavController(bottomNavigationView!!, navController!!)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
// Process the authorization result to obtain the authorization code from AuthAccount.
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == 1234) {
Log.e("TAG", " Result can be pulled")
}
if (requestCode == 8888) {
val authAccountTask = AccountAuthManager.parseAuthResultFromIntent(data)
if (authAccountTask.isSuccessful) {
// The sign-in is successful, and the user's ID information and authorization code are obtained.
val authAccount = authAccountTask.result
val userData = UserData()
userData.accessToken = authAccount.accessToken
userData.countryCode = authAccount.countryCode
userData.displayName = authAccount.displayName
userData.email = authAccount.email
userData.familyName = authAccount.familyName
userData.givenName = authAccount.givenName
userData.idToken = authAccount.idToken
userData.openId = authAccount.openId
userData.uid = authAccount.uid
userData.photoUriString = authAccount.avatarUri.toString()
userData.unionId = authAccount.unionId
loginViewModel = ViewModelProvider([email protected]).get(
LoginViewModel::class.java
)
loginViewModel!!.sendData(authAccount.displayName)
} else {
// The sign-in failed.
Log.e(
"TAG",
"sign in failed:" + (authAccountTask.exception as ApiException).statusCode
)
}
}
if ((requestCode == 2323) && (resultCode == RESULT_OK) && (data != null)) {
progressDialog!!.setMessage("Initializing text detection..")
progressDialog!!.show()
imagePath = data.data
try {
bitmap = MediaStore.Images.Media.getBitmap(this.contentResolver, imagePath)
asyncAnalyzeText(bitmap)
} catch (e: IOException) {
e.printStackTrace()
Log.e("TAG", " BITMAP ERROR")
}
}
if ((requestCode == 2424) && (resultCode == RESULT_OK) && (data != null)) {
progressDialog!!.setMessage("Initializing text detection..")
progressDialog!!.show()
try {
bitmap = data.extras!!["data"] as Bitmap?
asyncAnalyzeText(bitmap)
} catch (e: Exception) {
e.printStackTrace()
Log.e("TAG", " BITMAP ERROR")
}
}
}
private fun asyncAnalyzeText(bitmap: Bitmap?) {
if (mTextAnalyzer == null) {
createMLTextAnalyzer()
}
val frame = MLFrame.fromBitmap(bitmap)
val task = mTextAnalyzer!!.asyncAnalyseFrame(frame)
task.addOnSuccessListener(object : OnSuccessListener<MLText> {
override fun onSuccess(text: MLText) {
progressDialog!!.setMessage("Initializing language detection..")
textRecognized = text.stringValue.trim { it <= ' ' }
if (!textRecognized!!.isEmpty()) {
// Create a local language detector.
val factory = MLLangDetectorFactory.getInstance()
val setting =
MLLocalLangDetectorSetting.Factory() // Set the minimum confidence threshold for language detection.
.setTrustedThreshold(0.01f)
.create()
myLocalLangDetector = factory.getLocalLangDetector(setting)
val firstBestDetectTask = myLocalLangDetector!!.firstBestDetect(textRecognized)
firstBestDetectTask.addOnSuccessListener(OnSuccessListener { languageDetected ->
progressDialog!!.setMessage("Initializing text translation..")
// Processing logic for detection success.
textTranslate(languageDetected, textRecognized!!, bitmap)
}).addOnFailureListener(object : OnFailureListener {
override fun onFailure(e: Exception) {
// Processing logic for detection failure.
Log.e("TAG", "Lang detect error:" + e.message)
}
})
} else {
progressDialog!!.dismiss()
showErrorDialog("Failed to recognize text.")
}
}
}).addOnFailureListener(object : OnFailureListener {
override fun onFailure(e: Exception) {
Log.e("TAG", "#==>" + e.message)
}
})
}
private fun showErrorDialog(msg: String) {
val alertDialog = AlertDialog.Builder(this).create()
alertDialog.setTitle("Error")
alertDialog.setMessage(msg)
alertDialog.setButton(
AlertDialog.BUTTON_POSITIVE,
"OK",
object : DialogInterface.OnClickListener {
override fun onClick(dialog: DialogInterface, which: Int) {
dialog.dismiss()
}
})
alertDialog.show()
}
private fun textTranslate(languageDetected: String, textRecognized: String, uri: Bitmap?) {
MLApplication.initialize(application)
MLApplication.getInstance().apiKey = Constants.API_KEY
// Create an offline translator.
val setting =
MLLocalTranslateSetting.Factory() // Set the source language code. The ISO 639-1 standard is used. This parameter is mandatory. If this parameter is not set, an error may occur.
.setSourceLangCode(languageDetected) // Set the target language code. The ISO 639-1 standard is used. This parameter is mandatory. If this parameter is not set, an error may occur.
.setTargetLangCode("en")
.create()
myLocalTranslator = MLTranslatorFactory.getInstance().getLocalTranslator(setting)
// Set the model download policy.
val downloadStrategy = MLModelDownloadStrategy.Factory()
.needWifi() // It is recommended that you download the package in a Wi-Fi environment.
.create()
// Create a download progress listener.
val modelDownloadListener: MLModelDownloadListener = object : MLModelDownloadListener {
override fun onProcess(alreadyDownLength: Long, totalLength: Long) {
runOnUiThread(object : Runnable {
override fun run() {
// Display the download progress or perform other operations.
}
})
}
}
myLocalTranslator!!.preparedModel(downloadStrategy, modelDownloadListener)
.addOnSuccessListener(object : OnSuccessListener<Void?> {
override fun onSuccess(aVoid: Void?) {
// Called when the model package is successfully downloaded.
// input is a string of less than 5000 characters.
val task = myLocalTranslator!!.asyncTranslate(textRecognized)
// Before translation, ensure that the models have been successfully downloaded.
task.addOnSuccessListener(object : OnSuccessListener<String> {
override fun onSuccess(translated: String) {
// Processing logic for detection success.
result.clear()
result.add(languageDetected.trim { it <= ' ' })
result.add(textRecognized.trim { it <= ' ' })
result.add(translated.trim { it <= ' ' })
loginViewModel!!.setImage(uri!!)
loginViewModel!!.setTextRecongnized(result)
progressDialog!!.dismiss()
}
}).addOnFailureListener(object : OnFailureListener {
override fun onFailure(e: Exception) {
// Processing logic for detection failure.
progressDialog!!.dismiss()
}
})
}
}).addOnFailureListener(object : OnFailureListener {
override fun onFailure(e: Exception) {
// Called when the model package fails to be downloaded.
progressDialog!!.dismiss()
}
})
}
private fun createMLTextAnalyzer() {
val setting = MLLocalTextSetting.Factory()
.setOCRMode(MLLocalTextSetting.OCR_DETECT_MODE)
.create()
mTextAnalyzer = MLAnalyzerFactory.getInstance().getLocalTextAnalyzer(setting)
}
override fun onStop() {
if (myLocalLangDetector != null) {
myLocalLangDetector!!.stop()
}
if (myLocalTranslator != null) {
myLocalTranslator!!.stop()
}
if (progressDialog != null) {
progressDialog!!.dismiss()
}
super.onStop()
}
companion object {
var TAG = "TAG"
}
}
LoginViewModel.kt
Java:
package com.huawei.hms.knowmyboard.dtse.activity.viewmodel
import android.app.Application
import com.huawei.hms.support.account.service.AccountAuthService
import android.graphics.Bitmap
import com.huawei.hms.location.LocationResult
import com.huawei.hms.site.api.model.Site
import android.widget.Toast
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.huawei.hms.common.ApiException
import com.huawei.hms.knowmyboard.dtse.R
import com.huawei.hms.support.account.request.AccountAuthParams
import com.huawei.hms.support.account.request.AccountAuthParamsHelper
import com.huawei.hms.support.account.AccountAuthManager
import com.huawei.hms.knowmyboard.dtse.activity.app.MyApplication
import java.util.ArrayList
class LoginViewModel(application: Application) : AndroidViewModel(application) {
var service: AccountAuthService? = null
val message = MutableLiveData<String>()
val textRecongnized = MutableLiveData<ArrayList<String>>()
val imagePath = MutableLiveData<Bitmap>()
val locationResult = MutableLiveData<LocationResult>()
val siteSelected = MutableLiveData<Site>()
fun getSiteSelected(): LiveData<Site> {
return siteSelected
}
fun setSiteSelected(siteSelected: Site) {
this.siteSelected.value = siteSelected
}
fun sendData(msg: String) {
message.value = msg
}
fun getMessage(): LiveData<String> {
return message
}
fun setImage(imagePath: Bitmap) {
this.imagePath.value = imagePath
}
fun setLocationResult(locationResult: LocationResult) {
this.locationResult.value = locationResult
}
fun setTextRecongnized(textRecongnized: ArrayList<String>) {
this.textRecongnized.value = textRecongnized
}
fun logoutHuaweiID() {
if (service != null) {
service!!.signOut()
sendData("KnowMyBoard")
Toast.makeText(getApplication(), "You are logged out from Huawei ID", Toast.LENGTH_LONG)
.show()
}
}
fun loginClicked() {
val authParams =
AccountAuthParamsHelper(AccountAuthParams.DEFAULT_AUTH_REQUEST_PARAM).setAuthorizationCode()
.createParams()
service = AccountAuthManager.getService(MyApplication.activity, authParams)
MyApplication.activity!!.startActivityForResult(service!!.signInIntent, 8888)
}
fun cancelAuthorization() {
if (service != null) {
// service indicates the AccountAuthService instance generated using the getService method during the sign-in authorization.
service!!.cancelAuthorization().addOnCompleteListener { task ->
if (task.isSuccessful) {
// Processing after a successful authorization cancellation.
sendData(getApplication<Application>().resources.getResourceName(R.string.app_name))
Toast.makeText(getApplication(), "Cancelled authorization", Toast.LENGTH_LONG)
.show()
} else {
// Handle the exception.
val exception = task.exception
if (exception is ApiException) {
val statusCode = exception.statusCode
Toast.makeText(
getApplication(),
"Failed to cancel authorization. status code $statusCode",
Toast.LENGTH_LONG
).show()
}
}
}
} else {
Toast.makeText(getApplication(), "Login required", Toast.LENGTH_LONG).show()
}
}
}
SearchFragment.kt
Java:
package com.huawei.hms.knowmyboard.dtse.activity.fragments
import androidx.navigation.Navigation.findNavController
import com.huawei.hms.knowmyboard.dtse.activity.viewmodel.LoginViewModel
import androidx.navigation.NavController
import com.huawei.hms.site.api.SearchService
import com.huawei.hms.knowmyboard.dtse.activity.adapter.SitesAdapter
import com.huawei.hms.site.api.model.Site
import com.huawei.hms.location.LocationResult
import com.huawei.hms.knowmyboard.dtse.activity.intefaces.ItemClickListener
import android.view.WindowManager
import android.view.LayoutInflater
import android.view.ViewGroup
import android.os.Bundle
import android.util.Log
import android.view.View
import androidx.appcompat.widget.SearchView
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.huawei.hms.knowmyboard.dtse.R
import com.huawei.hms.knowmyboard.dtse.activity.util.Constants
import com.huawei.hms.knowmyboard.dtse.databinding.FragmentSearchBinding
import com.huawei.hms.site.api.SearchServiceFactory
import com.huawei.hms.site.api.model.TextSearchRequest
import com.huawei.hms.site.api.model.Coordinate
import com.huawei.hms.site.api.SearchResultListener
import com.huawei.hms.site.api.model.TextSearchResponse
import com.huawei.hms.site.api.model.SearchStatus
import com.huawei.hms.site.api.model.NearbySearchRequest
import com.huawei.hms.site.api.model.HwLocationType
import com.huawei.hms.site.api.model.NearbySearchResponse
import java.io.UnsupportedEncodingException
import java.lang.Exception
import java.net.URLEncoder
import java.util.ArrayList
class SearchFragment : Fragment() {
var binding: FragmentSearchBinding? = null
var loginViewModel: LoginViewModel? = null
//View view;
var navController: NavController? = null
private var searchService: SearchService? = null
var adapter: SitesAdapter? = null
var siteArrayList = ArrayList<Site>()
var locationResult: LocationResult? = null
/* var siteClicklistener = ItemClickListener { vh, site, pos ->
requireActivity().window.setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN
)
loginViewModel!!.setSiteSelected(site)
navController!!.navigate(R.id.loginFragment)
}*/
var siteClicklistener = object : ItemClickListener{
override fun onItemClicked(vh: RecyclerView.ViewHolder?, item: Site?, pos: Int) {
requireActivity().window.setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN
)
loginViewModel!!.setSiteSelected(item!!)
navController!!.navigate(R.id.loginFragment)
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
requireActivity().window.setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE
)
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_search, container, false)
loginViewModel = ViewModelProvider(requireActivity()).get(
LoginViewModel::class.java
)
val searchView = binding!!.edSearch
val recyclerView = binding!!.suggestionRv
navController = findNavController(requireActivity(), R.id.nav_host_fragment)
searchView.isFocusable = true
searchView.onActionViewExpanded()
adapter = SitesAdapter(siteArrayList, context, siteClicklistener)
recyclerView.adapter = adapter
recyclerView.layoutManager = LinearLayoutManager(context)
recyclerView.setHasFixedSize(true)
loginViewModel!!.locationResult.observeForever { locationResult1 ->
locationResult = locationResult1
}
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String): Boolean {
return false
}
override fun onQueryTextChange(newText: String): Boolean {
if (newText.length > 4) {
nearByPlacesSearch(newText)
}
return false
}
})
return binding!!.root
}
fun keywordSearch(search: String?) {
try {
val key = URLEncoder.encode(Constants.API_KEY, "UTF-8")
// Instantiate the SearchService object.
searchService = SearchServiceFactory.create(context, key)
// Create a request body.
val request = TextSearchRequest()
request.query = search
if (locationResult != null) {
val location = Coordinate(
locationResult!!.lastHWLocation.latitude,
locationResult!!.lastHWLocation.longitude
)
request.location = location
}
request.radius = 1000
//request.setHwPoiType(HwLocationType.HOTEL_MOTEL);
request.countryCode = "IN"
request.language = "en"
request.pageIndex = 1
request.pageSize = 5
request.isChildren = false
// request.setCountries(Arrays.asList("en", "fr", "cn", "de", "ko","in"));
// Create a search result listener.
val resultListener: SearchResultListener<TextSearchResponse?> =
object : SearchResultListener<TextSearchResponse?> {
// Return search results upon a successful search.
override fun onSearchResult(results: TextSearchResponse?) {
if (results == null || results.totalCount <= 0) {
return
}
val sites = results.sites
if (sites == null || sites.size == 0) {
return
}
siteArrayList.clear()
for (site in sites) {
siteArrayList.add(site)
}
siteArrayList.addAll(sites)
adapter!!.notifyDataSetChanged()
}
// Return the result code and description upon a search exception.
override fun onSearchError(status: SearchStatus) {
Log.i("TAG", "Error : " + status.errorCode + " " + status.errorMessage)
}
}
// Call the keyword search API.
searchService!!.textSearch(request, resultListener)
} catch (e: UnsupportedEncodingException) {
e.printStackTrace()
}
}
fun nearByPlacesSearch(newText: String?) {
try {
val key = URLEncoder.encode(Constants.API_KEY, "UTF-8")
// Instantiate the SearchService object.
searchService = SearchServiceFactory.create(context, key)
// Create a request body.
val request = NearbySearchRequest()
if (locationResult != null) {
val location = Coordinate(
locationResult!!.lastHWLocation.latitude,
locationResult!!.lastHWLocation.longitude
)
request.location = location
}
request.query = newText
request.radius = 1000
request.hwPoiType = HwLocationType.ADDRESS
request.language = "en"
request.pageIndex = 1
request.pageSize = 5
request.strictBounds = false
// Create a search result listener.
val resultListener: SearchResultListener<NearbySearchResponse?> =
object : SearchResultListener<NearbySearchResponse?> {
// Return search results upon a successful search.
override fun onSearchResult(results: NearbySearchResponse?) {
if (results == null || results.totalCount <= 0) {
return
}
val sites = results.sites
if (sites == null || sites.size == 0) {
return
}
siteArrayList.clear()
for (site in sites) {
siteArrayList.add(site)
}
siteArrayList.addAll(sites)
adapter!!.notifyDataSetChanged()
}
// Return the result code and description upon a search exception.
override fun onSearchError(status: SearchStatus) {
Log.i("TAG", "Error : " + status.errorCode + " " + status.errorMessage)
}
}
// Call the nearby place search API.
searchService!!.nearbySearch(request, resultListener)
} catch (e: Exception) {
e.printStackTrace()
}
}
}
RequestLocationData.kt
Java:
package com.huawei.hms.knowmyboard.dtse.activity.util
import android.Manifest
import com.huawei.hms.knowmyboard.dtse.activity.viewmodel.LoginViewModel
import android.app.Activity
import android.content.Context
import android.os.Build
import android.content.pm.PackageManager
import android.os.Looper
import android.location.Geocoder
import android.util.Log
import androidx.annotation.RequiresApi
import androidx.core.app.ActivityCompat
import androidx.fragment.app.FragmentActivity
import com.huawei.hms.location.*
import java.io.IOException
import java.lang.StringBuilder
import java.util.*
class RequestLocationData(
context: Context?,
activity: FragmentActivity?,
loginViewModel: LoginViewModel?
) {
private var settingsClient: SettingsClient? = null
private var isLocationSettingSuccess = 0
private var myLocationRequest: LocationRequest? = null
// Define a fusedLocationProviderClient object.
private var fusedLocationProviderClient: FusedLocationProviderClient? = null
private var myLocationCallback: LocationCallback? = null
var context: Context? = null
var activity: Activity? = null
private var locationResult: LocationResult? = null
var loginViewModel: LoginViewModel? = null
fun initFusionLocationProviderClint() {
// Instantiate the fusedLocationProviderClient object.
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(activity)
this.settingsClient = LocationServices.getSettingsClient(activity)
}
fun checkDeviceLocationSettings() {
val builder = LocationSettingsRequest.Builder()
myLocationRequest = LocationRequest()
builder.addLocationRequest(myLocationRequest)
val locationSettingsRequest = builder.build()
// Check the device location settings.
settingsClient!!.checkLocationSettings(locationSettingsRequest) // Define the listener for success in calling the API for checking device location settings.
.addOnSuccessListener { locationSettingsResponse: LocationSettingsResponse ->
val locationSettingsStates = locationSettingsResponse.locationSettingsStates
val stringBuilder = StringBuilder()
// Check whether the location function is enabled.
stringBuilder.append(",\nisLocationUsable=")
.append(locationSettingsStates.isLocationUsable)
// Check whether HMS Core (APK) is available.
stringBuilder.append(",\nisHMSLocationUsable=")
.append(locationSettingsStates.isHMSLocationUsable)
Log.i(TAG, "checkLocationSetting onComplete:$stringBuilder")
// Set the location type.
myLocationRequest!!.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
// Set the number of location updates to 1.
myLocationRequest!!.numUpdates = 1
isLocationSettingSuccess = 1
} // Define callback for failure in checking the device location settings.
.addOnFailureListener { e -> Log.i(TAG, "checkLocationSetting onFailure:" + e.message) }
}
@RequiresApi(Build.VERSION_CODES.S)
fun checkPermission() {
// Dynamically apply for required permissions if the API level is 28 or lower.
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
Log.i(TAG, "android sdk <= 28 Q")
if (ActivityCompat.checkSelfPermission(
context!!,
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(
context!!,
Manifest.permission.ACCESS_COARSE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
val strings = arrayOf(
Manifest.permission.CAMERA,
Manifest.permission.MANAGE_MEDIA,
Manifest.permission.MEDIA_CONTENT_CONTROL,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
)
ActivityCompat.requestPermissions(activity!!, strings, 1)
}
} else {
// Dynamically apply for the android.permission.ACCESS_BACKGROUND_LOCATION permission in addition to the preceding permissions if the API level is higher than 28.
if (ActivityCompat.checkSelfPermission(
activity!!,
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
context!!,
Manifest.permission.ACCESS_COARSE_LOCATION
) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
context!!,
"android.permission.ACCESS_BACKGROUND_LOCATION"
) != PackageManager.PERMISSION_GRANTED
) {
val strings = arrayOf(
Manifest.permission.CAMERA,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.MEDIA_CONTENT_CONTROL,
Manifest.permission.MANAGE_MEDIA,
"android.permission.ACCESS_BACKGROUND_LOCATION"
)
ActivityCompat.requestPermissions(activity!!, strings, 2)
}
}
}
fun refreshLocation(): LocationResult? {
Log.d(TAG, "Refreshing location")
if (isLocationSettingSuccess == 1) {
myLocationCallback = object : LocationCallback() {
private var locationResult: LocationResult? = null
override fun onLocationResult(locationResult: LocationResult) {
if (locationResult != null) {
// Gson gson = new Gson();
//Log.d(TAG, " Location data :" + locationResult.getLastLocation().getLatitude() + " : " + locationResult.getLastLocation().getLongitude());
//Log.d(TAG, " Location data :" + gson.toJson(locationResult.getLastHWLocation()));
//Log.d(TAG, " Location data :" + locationResult.getLastHWLocation().getCountryName());
Log.d(TAG, " Location data :" + locationResult.lastHWLocation.latitude)
Log.d(TAG, " Location data :" + locationResult.lastHWLocation.longitude)
// binding.textDetected.setText("Latitude " + locationResult.getLastHWLocation().getLatitude() + " Longitude " + locationResult.getLastHWLocation().getLongitude());
//getGeoCoderValues(locationResult.getLastHWLocation().getLatitude(),locationResult.getLastHWLocation().getLongitude());
this.locationResult = locationResult
loginViewModel!!.setLocationResult(locationResult)
}
}
}
fusedLocationProviderClient!!.requestLocationUpdates(
myLocationRequest,
myLocationCallback,
Looper.getMainLooper()
)
} else {
Log.d(TAG, "Failed to get location settings")
}
return locationResult
}
fun disableLocationData() {
fusedLocationProviderClient!!.disableBackgroundLocation()
fusedLocationProviderClient!!.removeLocationUpdates(myLocationCallback)
}
private fun getGeoCoderValues(latitude: Double, longitude: Double) {
getAddress(context, latitude, longitude)
/* Geocoder geocoder;
List<Address> addresses;
Locale locale = new Locale("en", "IN");
geocoder = new Geocoder(getContext(), locale);
try {
addresses = geocoder.getFromLocation(latitude, longitude, 1); // Here 1 represent max location result to returned, by documents it recommended 1 to 5
Gson gson=new Gson();
Log.d(TAG,"Geo coder :"+gson.toJson(addresses));
String address = addresses.get(0).getAddressLine(0); // If any additional address line present than only, check with max available address lines by getMaxAddressLineIndex()
String city = addresses.get(0).getLocality();
String state = addresses.get(0).getAdminArea();
String country = addresses.get(0).getCountryName();
String postalCode = addresses.get(0).getPostalCode();
String knownName = addresses.get(0).getFeatureName();
} catch (IOException e) {
e.printStackTrace();
Log.e(TAG,"Error while fetching Geo coder :"+e.getMessage());
}*/
/* Locale locale = new Locale("en", "IN");
GeocoderService geocoderService =
LocationServices.getGeocoderService(getActivity().getBaseContext(), locale);
// Request reverse geocoding.
GetFromLocationRequest getFromLocationRequest = new GetFromLocationRequest(latitude, longitude, 5);
// Initiate reverse geocoding.
geocoderService.getFromLocation(getFromLocationRequest)
.addOnSuccessListener(hwLocation -> {
Gson gson=new Gson();
Log.d(TAG,"Geo coder :"+gson.toJson(hwLocation));
})
.addOnFailureListener(e -> {
Log.e(TAG,"Error while fetching Geo coder :"+e.getMessage());
});*/
}
companion object {
var TAG = "TAG"
fun getAddress(context: Context?, LATITUDE: Double, LONGITUDE: Double) {
//Set Address
try {
val geocoder = Geocoder(context, Locale.getDefault())
val addresses = geocoder.getFromLocation(LATITUDE, LONGITUDE, 1)
if (addresses != null && addresses.size > 0) {
val address =
addresses[0].getAddressLine(0) // If any additional address line present than only, check with max available address lines by getMaxAddressLineIndex()
val city = addresses[0].locality
val state = addresses[0].adminArea
val country = addresses[0].countryName
val postalCode = addresses[0].postalCode
val knownName = addresses[0].featureName // Only if available else return NULL
Log.d(TAG, "getAddress: address$address")
Log.d(TAG, "getAddress: city$city")
Log.d(TAG, "getAddress: state$state")
Log.d(TAG, "getAddress: postalCode$postalCode")
Log.d(TAG, "getAddress: knownName$knownName")
}
} catch (e: IOException) {
e.printStackTrace()
Log.e(TAG, "Error while fetching Geo coder :" + e.message)
}
}
}
init {
[email protected] = context
[email protected] = activity
[email protected] = loginViewModel
}
}
navigation_graph.xml
XML:
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/navigation_graph"
app:startDestination="@id/loginFragment">
<fragment
android:id="@+id/loginFragment"
android:name="com.huawei.hms.knowmyboard.dtse.activity.fragments.LoginFragment"
android:label="LoginFragment"/>
<fragment
android:id="@+id/mainFragment"
android:name="com.huawei.hms.knowmyboard.dtse.activity.fragments.MainFragment"
android:label="MainFragment"/>
<fragment
android:id="@+id/searchFragment"
android:name="com.huawei.hms.knowmyboard.dtse.activity.fragments.SearchFragment"
android:label="fragment_search"
tools:layout="@layout/fragment_search" />
</navigation>
bottom_navigation_menu.xml
XML:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/searchFragment"
android:icon="@android:drawable/ic_menu_search"
android:title="@string/search" />
<item
android:id="@+id/loginFragment"
android:icon="@android:drawable/ic_menu_agenda"
android:title="Home" />
<item
android:id="@+id/mainFragment"
app:showAsAction="always"
android:icon="@android:drawable/ic_menu_gallery"
android:title="Gallery" />
</menu>
Result
{
"lightbox_close": "Close",
"lightbox_next": "Next",
"lightbox_previous": "Previous",
"lightbox_error": "The requested content cannot be loaded. Please try again later.",
"lightbox_start_slideshow": "Start slideshow",
"lightbox_stop_slideshow": "Stop slideshow",
"lightbox_full_screen": "Full screen",
"lightbox_thumbnails": "Thumbnails",
"lightbox_download": "Download",
"lightbox_share": "Share",
"lightbox_zoom": "Zoom",
"lightbox_new_window": "New window",
"lightbox_toggle_sidebar": "Toggle sidebar"
}
Tricks and Tips
Makes sure that agconnect-services.json file added.
Make sure required dependencies are added
Make sure that service is enabled in AGC
Enable data binding in gradle.build file
Make sure bottom navigation id's should be same as fragment id's in navigation graph
Conclusion
In this article, we have learnt how to integrate Huawei Site Kit, Map kit, Location kit in Android application KnowMyBoard. Hoping that the Map kit capabilities are helpful to you as well, like this sample, you can make use of Site kit as per your requirement.
Reference
Map Kit – Training video
Site Kit – Training video