Android MediaBrowserService customize audio src and meta data - java

I am building a audio player i have completed all the Songs browsing (UI) activities and to handle audio playback i am using google sample audio player this and i read all the src from this sample and there is class MusicLibrary in sample code and it contains a sample list of songs like below
public class MusicLibrary {
private static final TreeMap<String, MediaMetadataCompat> music = new TreeMap<>();
private static final HashMap<String, Integer> albumRes = new HashMap<>();
private static final HashMap<String, String> musicFileName = new HashMap<>();
static {
createMediaMetadataCompat(
"Jazz_In_Paris",
"Jazz in Paris",
"Media Right Productions",
"Jazz & Blues",
"Jazz",
103,
TimeUnit.SECONDS,
"http://www.noiseaddicts.com/samples_1w72b820/2537.mp3",
R.drawable.album_jazz_blues,
"https://upload.wikimedia.org/wikipedia/en/a/ac/Audioslave_-_Audioslave.jpg");
createMediaMetadataCompat(
"The_Coldest_Shoulder",
"The Coldest Shoulder",
"The 126ers",
"Youtube Audio Library Rock 2",
"Rock",
160,
TimeUnit.SECONDS,
"http://www.noiseaddicts.com/samples_1w72b820/4201.mp3",
R.drawable.album_youtube_audio_library_rock_2,
"https://theflagcompany.in/wp-content/uploads/2018/10/Indian-National-Flag-300x300.jpeg");
}
but i am unable to find a method which shows how to add a song in current playlist from other activities for example in my current app there is search activity where user can search any song from internet and i want to add track from this search activity by two different ways 1. add and play song 2. only add song in the end of playlist.
Sample code track object use album art image from drawable folder but in my app i need to show album art from internet (Last FM API) not from local folder i tried to edit MusicLibrary class and created a bitmap from URI unable to make it work so this is alos i need to modify in sample code.
Sample code contains only on simple activity where when you open it opens a audio player interface but in my app in HomeActivity there are some fragments and a mini player at bottom now like below
Please help me with these two things
add songs to player from my code
use internet image for METADATA_KEY_ALBUM_ART
i just want to merge these two things and i am new to android so no luck please guide me so that i can complete my project. Thanks in advance :)
My Main Activity
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
//add song in sample player service from this method
public void addSongQue(Song song) {
title = song.getTile;
artist = song.getArtist;
mp3Url = song.getSrc;
albumArtImage = song.getAlbumArt;
.......
...
}
}
Sample Code Player Activity full sample src is here
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.media.MediaBrowserCompat;
import android.support.v4.media.MediaMetadataCompat;
import android.support.v4.media.session.MediaControllerCompat;
import android.support.v4.media.session.MediaSessionCompat;
import android.support.v4.media.session.PlaybackStateCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import com.example.android.mediasession.R;
import com.example.android.mediasession.client.MediaBrowserHelper;
import com.example.android.mediasession.service.MusicService;
import com.example.android.mediasession.service.contentcatalogs.MusicLibrary;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private ImageView mAlbumArt;
private TextView mTitleTextView;
private TextView mArtistTextView;
private ImageView mMediaControlsImage;
private MediaSeekBar mSeekBarAudio;
private MediaBrowserHelper mMediaBrowserHelper;
private boolean mIsPlaying;
//https://github.com/googlesamples/android-MediaBrowserService
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTitleTextView = findViewById(R.id.song_title);
mArtistTextView = findViewById(R.id.song_artist);
mAlbumArt = findViewById(R.id.album_art);
mMediaControlsImage = findViewById(R.id.media_controls);
mSeekBarAudio = findViewById(R.id.seekbar_audio);
final ClickListener clickListener = new ClickListener();
findViewById(R.id.button_previous).setOnClickListener(clickListener);
findViewById(R.id.button_play).setOnClickListener(clickListener);
findViewById(R.id.button_next).setOnClickListener(clickListener);
mMediaBrowserHelper = new MediaBrowserConnection(this);
mMediaBrowserHelper.registerCallback(new MediaBrowserListener());
}
#Override
public void onStart() {
super.onStart();
mMediaBrowserHelper.onStart();
}
#Override
public void onStop() {
super.onStop();
mSeekBarAudio.disconnectController();
mMediaBrowserHelper.onStop();
}
/**
* Convenience class to collect the click listeners together.
* <p>
* In a larger app it's better to split the listeners out or to use your favorite
* library.
*/
private class ClickListener implements View.OnClickListener {
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button_previous:
mMediaBrowserHelper.getTransportControls().skipToPrevious();
break;
case R.id.button_play:
if (mIsPlaying) {
mMediaBrowserHelper.getTransportControls().pause();
} else {
mMediaBrowserHelper.getTransportControls().play();
}
break;
case R.id.button_next:
mMediaBrowserHelper.getTransportControls().skipToNext();
break;
}
}
}
/**
* Customize the connection to our {#link android.support.v4.media.MediaBrowserServiceCompat}
* and implement our app specific desires.
*/
private class MediaBrowserConnection extends MediaBrowserHelper {
private MediaBrowserConnection(Context context) {
super(context, MusicService.class);
}
#Override
protected void onConnected(#NonNull MediaControllerCompat mediaController) {
mSeekBarAudio.setMediaController(mediaController);
}
#Override
protected void onChildrenLoaded(#NonNull String parentId,
#NonNull List<MediaBrowserCompat.MediaItem> children) {
super.onChildrenLoaded(parentId, children);
final MediaControllerCompat mediaController = getMediaController();
// Queue up all media items for this simple sample.
for (final MediaBrowserCompat.MediaItem mediaItem : children) {
mediaController.addQueueItem(mediaItem.getDescription());
}
// Call prepare now so pressing play just works.
mediaController.getTransportControls().prepare();
}
}
/**
* Implementation of the {#link MediaControllerCompat.Callback} methods we're interested in.
* <p>
* Here would also be where one could override
* {#code onQueueChanged(List<MediaSessionCompat.QueueItem> queue)} to get informed when items
* are added or removed from the queue. We don't do this here in order to keep the UI
* simple.
*/
private class MediaBrowserListener extends MediaControllerCompat.Callback {
#Override
public void onPlaybackStateChanged(PlaybackStateCompat playbackState) {
mIsPlaying = playbackState != null &&
playbackState.getState() == PlaybackStateCompat.STATE_PLAYING;
mMediaControlsImage.setPressed(mIsPlaying);
}
#Override
public void onMetadataChanged(MediaMetadataCompat mediaMetadata) {
if (mediaMetadata == null) {
return;
}
mTitleTextView.setText(
mediaMetadata.getString(MediaMetadataCompat.METADATA_KEY_TITLE));
mArtistTextView.setText(
mediaMetadata.getString(MediaMetadataCompat.METADATA_KEY_ARTIST));
mAlbumArt.setImageBitmap(MusicLibrary.getAlbumBitmap(
MainActivity.this,
mediaMetadata.getString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID)));
}
#Override
public void onSessionDestroyed() {
super.onSessionDestroyed();
}
#Override
public void onQueueChanged(List<MediaSessionCompat.QueueItem> queue) {
super.onQueueChanged(queue);
}
}
}
MusicLibrary Class where two sample songs
import android.content.ContentResolver;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.support.v4.media.MediaBrowserCompat;
import android.support.v4.media.MediaMetadataCompat;
import com.example.android.mediasession.BuildConfig;
import com.example.android.mediasession.R;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.TreeMap;
import java.util.concurrent.TimeUnit;
public class MusicLibrary {
private static final TreeMap<String, MediaMetadataCompat> music = new TreeMap<>();
private static final HashMap<String, Integer> albumRes = new HashMap<>();
private static final HashMap<String, String> musicFileName = new HashMap<>();
static {
createMediaMetadataCompat(
"Jazz_In_Paris",
"Jazz in Paris",
"Media Right Productions",
"Jazz & Blues",
"Jazz",
103,
TimeUnit.SECONDS,
"http://www.noiseaddicts.com/samples_1w72b820/2537.mp3",
R.drawable.album_jazz_blues,
"https://upload.wikimedia.org/wikipedia/en/a/ac/Audioslave_-_Audioslave.jpg");
createMediaMetadataCompat(
"The_Coldest_Shoulder",
"The Coldest Shoulder",
"The 126ers",
"Youtube Audio Library Rock 2",
"Rock",
160,
TimeUnit.SECONDS,
"http://www.noiseaddicts.com/samples_1w72b820/4201.mp3",
R.drawable.album_youtube_audio_library_rock_2,
"https://theflagcompany.in/wp-content/uploads/2018/10/Indian-National-Flag-300x300.jpeg");
}
public static String getRoot() {
return "root";
}
private static String getAlbumArtUri(String albumArtResName) {
return ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
BuildConfig.APPLICATION_ID + "/drawable/" + albumArtResName;
}
public static String getMusicFilename(String mediaId) {
return musicFileName.containsKey(mediaId) ? musicFileName.get(mediaId) : null;
}
private static int getAlbumRes(String mediaId) {
return albumRes.containsKey(mediaId) ? albumRes.get(mediaId) : 0;
}
public static Bitmap getAlbumBitmap(Context context, String mediaId) {
return BitmapFactory.decodeResource(context.getResources(),
MusicLibrary.getAlbumRes(mediaId));
}
public static List<MediaBrowserCompat.MediaItem> getMediaItems() {
List<MediaBrowserCompat.MediaItem> result = new ArrayList<>();
for (MediaMetadataCompat metadata : music.values()) {
result.add(
new MediaBrowserCompat.MediaItem(
metadata.getDescription(), MediaBrowserCompat.MediaItem.FLAG_PLAYABLE));
}
return result;
}
public static MediaMetadataCompat getMetadata(Context context, String mediaId) {
MediaMetadataCompat metadataWithoutBitmap = music.get(mediaId);
Bitmap albumArt = getAlbumBitmap(context, mediaId);
// Since MediaMetadataCompat is immutable, we need to create a copy to set the album art.
// We don't set it initially on all items so that they don't take unnecessary memory.
MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder();
for (String key :
new String[]{
MediaMetadataCompat.METADATA_KEY_MEDIA_ID,
MediaMetadataCompat.METADATA_KEY_ALBUM,
MediaMetadataCompat.METADATA_KEY_ARTIST,
MediaMetadataCompat.METADATA_KEY_GENRE,
MediaMetadataCompat.METADATA_KEY_TITLE
}) {
builder.putString(key, metadataWithoutBitmap.getString(key));
}
builder.putLong(
MediaMetadataCompat.METADATA_KEY_DURATION,
metadataWithoutBitmap.getLong(MediaMetadataCompat.METADATA_KEY_DURATION));
builder.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, albumArt);
return builder.build();
}
private static void createMediaMetadataCompat(
String mediaId,
String title,
String artist,
String album,
String genre,
long duration,
TimeUnit durationUnit,
String musicFilename,
int albumArtResId,
String albumArtResName) {
music.put(
mediaId,
new MediaMetadataCompat.Builder()
.putString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID, mediaId)
.putString(MediaMetadataCompat.METADATA_KEY_ALBUM, album)
.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, artist)
.putLong(MediaMetadataCompat.METADATA_KEY_DURATION,
TimeUnit.MILLISECONDS.convert(duration, durationUnit))
.putString(MediaMetadataCompat.METADATA_KEY_GENRE, genre)
.putString(
MediaMetadataCompat.METADATA_KEY_ALBUM_ART_URI,
getAlbumArtUri(albumArtResName))
.putString(
MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON_URI,
getAlbumArtUri(albumArtResName))
.putString(MediaMetadataCompat.METADATA_KEY_TITLE, title)
.build());
albumRes.put(mediaId, albumArtResId);
musicFileName.put(mediaId, musicFilename);
}
}

Related

How can I populate a ListView on a SecondActivity with data from FirstActivity in Android?

I'm working on a book-searching app project. The user enters a title, and the app searches Google Books for it.
I initially had one activity and layout. I decided to use two layouts (one for user to enter title, and the other displays results); had to create another activity because the results layout was throwing an exception about 'null' object reference.
After creating the second activity, I used an intent to transfer List data between the two activities; no sooner did I find out that I had to use a Serialize or Parcelable object for the purpose.
Following instructions at Pass list of objects from one activity to other activity in android & https://www.vogella.com/tutorials/AndroidParcelable/article.html, I failed at implementing both, because Serialize sent an empty ArrayList (thus, an empty results page, even though there're book hits) and Parcelable was throwing out different exceptions everytime I used it, probably because I'm using an ArrayAdapter to populate the ListView with books.
I don't think I'm ready to implement the API at https://www.vogella.com/tutorials/AutoValue/article.html and can't use Fragments as well. A better structure would be to use a single activity, View.GONE the background image I so much cherish, and display list of book objects under the search field. But it would be good to make a follow-up on Serialize & Parcelable -- for future projects.
So, fellow developers, what's the solution to this?
FirstActivity screenshot
SecondActivity screeenshot
Here's my code:
MainActivity:
package project.android.gbookslisting;
import android.app.LoaderManager;
import android.content.Intent;
import android.content.Loader;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import androidx.appcompat.app.AppCompatActivity;
import static project.android.gbookslisting.ResultsActivity.adapter;
//import android.support.v4.content.AsyncTaskLoader;
//import android.support.v7.app.AppCompatActivity;
public class ParamsActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<List<Book>>, Serializable {
private static final int LOADER_ID = 0;
private static String LOG_TAG = ParamsActivity.class.getName();
EditText text;
String query;
private LoaderManager loaderManager = getLoaderManager();
#Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.parameters);
Button query = findViewById(R.id.search_button);
text = findViewById(R.id.deets_field);
query.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick (View view) {
if (text.getText().toString().length() > 0) { loaderManager.initLoader(LOADER_ID, null, ParamsActivity.this);
} else if (text.getText().length() < 1) {
text.setHint("Please enter book title/details");
text.setHintTextColor(Color.RED);
}
}
});
}
#Override
public Loader<List<Book>> onCreateLoader (int i, Bundle bundle) {
query = text.getText().toString();
return new BookLoader(this, query);
}
#Override
public void onLoadFinished (Loader<List<Book>> loader, List<Book> data) {
// If there is a valid list of {#link Book}s, then add them to the adapter's dataset. This will trigger the ListView to update.
if (data != null && !data.isEmpty()) {
data = new ArrayList<Book>();
Intent i = new Intent(getApplicationContext(), ResultsActivity.class);
i.putExtra("data", (Serializable) data);
startActivity(i);
}
}
#Override
public void onLoaderReset (Loader loader) {
adapter = new Adapt(this, new ArrayList<Book>());
adapter.clear();
}
}
SecondActivity:
package project.android.gbookslisting;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.TextView;
import java.io.Serializable;
import java.util.ArrayList;
import androidx.appcompat.app.AppCompatActivity;
public class ResultsActivity extends AppCompatActivity implements Serializable {
static Adapt adapter;
static TextView emptyResult;
ListView bookEntries;
String LOG_TAG = ResultsActivity.class.getName();
#Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.hits_page);
Intent i = getIntent();
ArrayList<Book> books = (ArrayList<Book>) i.getSerializableExtra("data");
emptyResult = findViewById(R.id.matches_nill);
emptyResult.setText(R.string.matches0);
if (!books.isEmpty()) {
emptyResult.setVisibility(View.GONE);
// Create a new adapter that takes a rich (or otherwise empty) list of books as input
adapter = new Adapt(this, new ArrayList<Book>());
// Get the list of books from {#link Search}
bookEntries = findViewById(R.id.catalog);
bookEntries.setAdapter(adapter);
bookEntries.setEmptyView(emptyResult);
bookEntries.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick (AdapterView<?> adapterView, View view, int position, long l) {
// Find the current book that was clicked on
Book currentBook = adapter.getItem(position);
// Convert the String URL into a URI object (to pass into the Intent constructor)
Uri bookUri = Uri.parse(currentBook.getPage());
// Create a new intent to view the book URI
Intent websiteIntent = new Intent(Intent.ACTION_VIEW, bookUri);
// Send the intent to launch a new activity
startActivity(websiteIntent);
}
});
// adapter.clear();
adapter.addAll(books);
} else {
emptyResult.setVisibility(View.VISIBLE);
emptyResult.setText(R.string.matches0);
}
}
}
Book obj.:
package project.android.gbookslisting;
import java.io.Serializable;
import java.util.Date;
public class Book {
private String book_title;
private String author;
private String publishing_year;
private String page;
public Book (String theTitle, String theAuthor, String theYear, String thePage) {
this.book_title = theTitle;
this.author = theAuthor;
this.publishing_year = theYear;
this.page = thePage;
}
public Book setBook_title (String book_title) {
this.book_title = book_title;
return this;
}
public Book setAuthor (String author) {
this.author = author;
return this;
}
public Book setPublishing_year (String publishing_year) {
this.publishing_year = publishing_year;
return this;
}
public Book setPage (String page) {
this.page = page;
return this;
}
protected String getAuthor () {
return author;
}
protected String getPublishing_year () { return publishing_year; }
protected String getPage () {
return page;
}
protected String getBook_title () {
return book_title;
}
}
You can declare the a variable that will handle your data = new ArrayList<Book>(); as public static.. However it's not recommended for high level codebase but for the structures of yours, you can implement it.
just declare a variable like this above protected void onCreate() in FirstActivity ..
public static List<Book> book_data = new ArrayList<>();
and transfer the data from public void onLoadFinished (Loader<List<Book>> loader, List<Book> data) to book_data
#Override
public void onLoadFinished (Loader<List<Book>> loader, List<Book> data) {
// If there is a valid list of {#link Book}s, then add them to the adapter's dataset. This will trigger the ListView to update.
if (data != null && !data.isEmpty()) {
//data = new ArrayList<Book>();
book_data = data;
Intent i = new Intent(getApplicationContext(), ResultsActivity.class);
startActivity(i);
}
}`
You can also try to debug it if it contains a value
Log.d(TAG, String.valueOf(data.size()));
and in SecondActivity
#Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.hits_page);
List<Book> books = new ArrayList<>();
books = FirstActivity.book_data; //Get the data from the First Activity
....
....
}
All right, so I was able to correct my implementation of the Parcelable interface and the FirstActivity now passes data to SecondActivity. This is it:
package project.android.gbookslisting;
import android.os.Parcel;
import android.os.Parcelable;
public class Book implements Parcelable {
private String book_title;
private String author;
private String publishing_year;
private String page;
public Book (String theTitle, String theAuthor, String theYear, String thePage) {
this.book_title = theTitle;
this.author = theAuthor;
this.publishing_year = theYear;
this.page = thePage;
}
public Book(Parcel in) {
this.book_title = in.readString();
this.author = in.readString();
this.publishing_year = in.readString();
this.page = in.readString();
}
public static final Creator<Book> CREATOR = new Creator<Book>() {
#Override
public Book createFromParcel (Parcel in) {
return new Book(in);
}
#Override
public Book[] newArray (int size) {
return new Book[size];
}
};
protected String getAuthor () { return author; }
protected String getPublishing_year () { return publishing_year; }
protected String getPage () {
return page;
}
protected String getBook_title () {
return book_title;
}
#Override
public int describeContents () {
return 0;
}
#Override
public void writeToParcel (Parcel parcel, int flags) {
parcel.writeString(book_title);
parcel.writeString(author);
parcel.writeString(publishing_year);
parcel.writeString(page);
}
}
I've shared the repository on GitHub #GBooks Listing, pending more features/updates.
ResultsActivity
Sure looks lame, but I'll improve the theming & whatever affects appearance. Thanks.

Cannot launch an activity in android using intent [duplicate]

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 4 years ago.
I have 2 modules in my application as follow app and interface. interface was an imported aar file.
I am trying to launch an activity in the interface module but every time the application crashes. Launching activities on the app module works fine
I had tried the other solutions available in this forum but was in vain. Find the codes below
QuestionAnalyser class
package com.example.dell.bubblebot;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.widget.Toast;
import com.example.dell.yandexapilanguagetranslator.Translator;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import java.util.ArrayList;
import java.util.List;
public class QuestionAnalyser extends AppCompatActivity {
public static String question;
public static String[] words;
String entityIdentified;
static boolean identified = false;
DatabaseReference entityRef;
TranslatorServant t = new TranslatorServant();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_interface);
Translator.setKey ("trnsl.1.1.20181013T134643Z.debdb5811d6caba2.3a4daf18b25c9f4b97662d5e9ac45ed81b199c84");
}
public void analyse(String userQues) {
TranslatorServant t = new TranslatorServant();
question = userQues.replaceAll("\\p{Punct}|\\d", "");
// question = t.translateText(userQues).replaceAll("\\p{Punct}|\\d", "");
words = question.split(" ");
getEntity(words);
}
private void getEntity(final String[] words) {
entityRef = FirebaseDatabase.getInstance().getReference().child("IRAdata").child("Entities");
entityRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot entity : dataSnapshot.getChildren()) {
String[] synonyms = entity.child("syn").getValue().toString().split(",");
for (String syn : synonyms) {
for (String word : words) {
if (word.equalsIgnoreCase(syn) || question.equalsIgnoreCase(syn)) {
entityIdentified = entity.getKey();
identified = true;
}
}
}
}
check(words);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Toast.makeText(getApplicationContext(), databaseError.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
public void mimicOtherMessage(String message) {
ChatMessage chatMessage = new ChatMessage(message, false);
Interface.madapter.add(chatMessage);
}
public void mimicOtherMessage() {
ChatMessage chatMessage = new ChatMessage(null, false);
Interface.madapter.add(chatMessage);
}
public void check(String[] words) {
if (identified == true) {
initialiseEntityServant(entityIdentified, question, words);
}
if (identified == false) {
for (String yes : YesNo.yes) {
for (String w : words) {
if (w.equalsIgnoreCase(yes) || question.equalsIgnoreCase(yes)) {
identified = true;
entityIdentified = "basic";
initialiseEntityServant(entityIdentified, question, words);
}
}
for (String no : YesNo.no) {
for (String w : words) {
if (w.equalsIgnoreCase(no) || question.equalsIgnoreCase(no)) {
identified = true;
entityIdentified = "basic";
initialiseEntityServant(entityIdentified, question, words);
}
}
}
}
}
if (identified == false) {
mimicOtherMessage("Sorry, I failed to understand your question.");
}
}
private void initialiseEntityServant(String ent, final String userQues, final String[] words) {
if (ent.equalsIgnoreCase("cuisine")) {
cuisine c=new cuisine();
c.analyse();
}
if(ent.equalsIgnoreCase("basic")){
final List<String> urlsList = new ArrayList<String>();
final List<String> descList = new ArrayList<String>();
urlsList.add("https://media.timeout.com/images/103708802/image.jpg");
urlsList.add("\"https://images.myguide-cdn.com/mauritius/companies/eighty-eight-chinese-restaurant/large/eighty-eight-chinese-restaurant-492783.png");
descList.add("A Chinese dish of small steamed or fried savoury dumplings containing various fillings. Definitely worth a try");
descList.add("Traditionally, this Chinese chicken dish is a dry-stir fry — not a lot of sauce is added into Kung Pao chicken. However, with the amount of flavour explosions happening in this dish, you don’t miss OR want any more sauce.");
Intent i= new Intent(getApplicationContext(),gallery.class);
i.putExtra("urls",urlsList.toArray());
i.putExtra("desc",descList.toArray());
startActivity(i);
}
// will need to initialise other classes
}
//add class to check if question and answer already exists
}
In this code i am calling the gallery activity
gallery class:
package com.example.dell.bubblebot;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
public class gallery extends AppCompatActivity {
public static String[]desc;
public static TextView descTextbox;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_gallery);
descTextbox=(TextView)findViewById(R.id.desc);
ViewPager viewPager=findViewById(R.id.view_pager);
String[] imageUrls=getIntent().getStringArrayExtra("urls");
String [] descArr=getIntent().getStringArrayExtra("desc");
desc=descArr;
ViewPagerAdapter adapter= new ViewPagerAdapter(this,imageUrls);
viewPager.setAdapter(adapter);
}
}
Error message:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.samples.chatbotsample1, PID: 14653
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.content.Context.getApplicationContext()' on a null object reference
at android.content.ContextWrapper.getApplicationContext(ContextWrapper.java:112)
at com.example.dell.bubblebot.QuestionAnalyser.initialiseEntityServant(QuestionAnalyser.java:126)
at com.example.dell.bubblebot.QuestionAnalyser.check(QuestionAnalyser.java:93)
at com.example.dell.bubblebot.QuestionAnalyser$1.onDataChange(QuestionAnalyser.java:61)
at com.google.firebase.database.obfuscated.zzap.zza(com.google.firebase:firebase-database##16.0.3:75)
at com.google.firebase.database.obfuscated.zzca.zza(com.google.firebase:firebase-database##16.0.3:63)
at com.google.firebase.database.obfuscated.zzcd$1.run(com.google.firebase:firebase-database##16.0.3:55)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:7406)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
Notice:
Class A { ...
}
getApplicationContext belongs to abstract class Context, if you want to use this method in your custom class, the class should extends Context or any of its sub class, such as Application,Activity, etc.

ADK toolkit Android+Arduino store variable issue

I'm writing a program which is supposed to run "forever". The program is Android application for tablet which exchanges data with Arduino. I have already implemented the code for Arduino and Android, and it exchanges data very well. However, after 2 cycles of work, my instance of AdkManager becomes NULL. As I've read before, Android will null variables from time to time because it has limited resources. However here's the problem - the AdkManager has confirmed bug that once it has been closed, it can't be reopened. Thus I can't re-initiate the AdkManager instance and I need to store it somehow. So far I've been using Application extension. The code is below:
MyApplication:
package org.udoo.androidadkdemobidirect;
import android.app.Application;
import android.content.Context;
import android.hardware.usb.UsbManager;
import me.palazzetti.adktoolkit.AdkManager;
/**
* Created by admin on 8/18/16.
*/
public class MyApplication extends Application {
private String someVariable;
public String getSomeVariable() {
return someVariable;
}
public void setSomeVariable(String someVariable) {
this.someVariable = someVariable;
}
public static class sAdkManager{
private static sAdkManager ourInstance = null;
public static sAdkManager getInstance() {
if (ourInstance==null)
ourInstance = new sAdkManager();
return ourInstance;
}
private static AdkManager mAdkManager = null;
public void write(String s){
mAdkManager.writeSerial(s);
}
public String read(){
return mAdkManager.readSerial();
}
public void open(){
mAdkManager.open();
}
public void close(){
mAdkManager.close();
}
public boolean checkNull(){
return mAdkManager==null;
}
public static void init(Context context){
if(mAdkManager==null) {
mAdkManager = new AdkManager((UsbManager) context.getSystemService(Context.USB_SERVICE));
context.registerReceiver(mAdkManager.getUsbReceiver(), mAdkManager.getDetachedFilter());
}
}
private sAdkManager() {
}
}
}
MainActivity:
package org.udoo.androidadkdemobidirect;
import me.palazzetti.adktoolkit.AdkManager;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.hardware.usb.UsbManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.View;
import android.widget.TextView;
import android.widget.ToggleButton;
//import org.udoo.androidadkdemobidirect.sAdkManager;
public class MainActivity extends Activity{
// private static final String TAG = "UDOO_AndroidADKFULL";
private static String mAdkManager=null;
private ToggleButton buttonLED;
private TextView distance;
private AdkReadTask mAdkReadTask;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//
//// register a BroadcastReceiver to catch UsbManager.ACTION_USB_ACCESSORY_DETACHED action
// registerReceiver(mAdkManager.getUsbReceiver(), mAdkManager.getDetachedFilter());
buttonLED = (ToggleButton) findViewById(R.id.toggleButtonLed);
distance = (TextView) findViewById(R.id.textViewIntro);
// mAdkManager.open();
TextView tv = (TextView) findViewById(R.id.ppm);
if (mAdkManager==null){
tv.setText("ADK is null. init()");
mAdkManager = new String ("sometext");
}
else{
tv.setText("ADK is not null.");
}
if (MyApplication.sAdkManager.getInstance().checkNull()) {
distance.setText("Null before init");
MyApplication.sAdkManager.init(this);
}
if (MyApplication.sAdkManager.getInstance().checkNull()) {
distance.setText("Null after init");
}
MyApplication.sAdkManager.getInstance().open();
mAdkReadTask = new AdkReadTask();
mAdkReadTask.execute();
}
#Override
public void onResume() {
super.onResume();
}
#Override
public void onPause() {
super.onPause();
}
#Override
public void onDestroy() {
MyApplication.sAdkManager.getInstance().close();
// unregisterReceiver(mAdkManager.getUsbReceiver());
super.onDestroy();
}
// ToggleButton method - send message to SAM3X
public void blinkLED(View v){
if (buttonLED.isChecked()) {
TextView tvdbg = (TextView) findViewById(R.id.ppm);
tvdbg.setText("send 1");
// writeSerial() allows you to write a single char or a String object.
//mAdkManager.writeSerial("1");
MyApplication.sAdkManager.getInstance().write("1");
// mAdkManager.writeSerial("8");
} else {
//mAdkManager.writeSerial("0");
MyApplication.sAdkManager.getInstance().write("0");
}
}
/*
* We put the readSerial() method in an AsyncTask to run the
* continuous read task out of the UI main thread
*/
private class AdkReadTask extends AsyncTask<Void, String, Void> {
private boolean running = true;
public void pause(){
running = false;
}
protected Void doInBackground(Void... params) {
// Log.i("ADK demo bi", "start adkreadtask");
while(running) {
// if (mAdkManager.serialAvailable())
// publishProgress(mAdkManager.readSerial()) ;
publishProgress(MyApplication.sAdkManager.getInstance().read());
}
return null;
}
protected void onProgressUpdate(String... progress) {
distance.setText("You put "+((int)progress[0].charAt(0)-48) + " iqos butts\tRFID OK");
next();
// Log.i(TAG, "received: " + (int)progress[0].charAt(0));
}
}
private void next() {
final Intent intent = new Intent(this, BRActivity.class );
new android.os.Handler().postDelayed(
new Runnable() {
public void run() {
mAdkReadTask.pause();
mAdkReadTask = null;
startActivity(intent);
}
},
3000);
}
}
There are just 2 Activities for now - MainActivity and BRActivity. BRActivity is just a view with "return" button which comes back to MainActivity.
Also what I find interesting - I output the readSerial in TextView to see what I got in reader thread. However on cycle#2 i don't get any output to TextView, but Activity still changes to the next one.
[EDIT]
Apparently the problem was solved when the thread was nulling. However, I still don't get the text update, but I magically get to another screen. Please advice.

Rewrite Android Function to start an Activity instead of dsplaying text

I am pretty new to Android Development and Java for that matter.
I am using an external library by a company that produces stamps that can be recognised on a touchscreen.
I get the application to start and display the stamp data, but I would like the application to start a new Activity once the stamp has been entered.
Please find the MainView.Class and StampActivity.Class below:
Mainview
import android.content.Context;
import android.content.Intent;
import android.util.AttributeSet;
import com.onetwocm.stamp.service.sdk.StampBaseView;
#SuppressWarnings("deprecation")
public class MainView extends StampBaseView {
public MainView(Context context) {
super(context);
}
public MainView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MainView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void onInitSuccess() {
StampActivity.setText("onInitSuccess");
}
public void onInitError(String code, String message) {
StampActivity.setText("onInitError - " + code + " " + message);
}
public void onStampSuccess(String stampResult) {
StampActivity.setText("onStampSuccess - " + stampResult);
}
public void onStampError(String code, String message) {
StampActivity.setText("onStampError - " + code + " " + message);
}
}
StampActivity.Class
import android.app.Activity;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.widget.TextView;
public class StampActivity extends Activity {
MainView mainView = null;
static TextView textView = null;
public static final int KOREA = 0;
public static final int TAIWAN = 1;
public static final int JAPAN = 2;
public static final int KOREAN = 0;
public static final int ENGLISH = 1;
public static final int CHINESE = 2;
public static final int JAPANESE = 3;
public static final int SPANISH = 4;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_echoss);
mainView = (MainView)findViewById(R.id.mainView);
textView = (TextView)findViewById(R.id.textView);
// String APIKEY = "xxxxx";
String APIKEY = "xxxxxx"; // Write you api key
int REGION = KOREA; // KOREA TAIWAN JAPAN
int LANGUAGE = ENGLISH; // KOREAN ENGLISH CHINESE JAPANESE SPANISH
String INDEX = "B"; // Write index value received from 12cm
// Display Initialization
DisplayMetrics metric = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metric);
mainView.init(metric);
// Library Initialization for Stamp
mainView.PlatformInit(APIKEY, REGION, LANGUAGE, INDEX);
}
#Override
public void onBackPressed() {
super.onBackPressed();
}
public static void setText(String text) {
textView.setText(text);
}
In the MainView Class exist the function onStampSuccess. Instead of returning text, I would like it to start a new activity.
I would be grateful for any help.
You should totally avoid static methods as the current structure makes your app highly susceptible to memory leaks! This can be achieved using interfaces. Firstly, in a new class define your interface method as (may add more later):
public interface MainViewActivityInterface {
public void stampSuccess(String text)
}
Now, modify your MainView to accept the above interface:
import android.content.Context;
import android.content.Intent;
import android.util.AttributeSet;
import com.onetwocm.stamp.service.sdk.StampBaseView;
#SuppressWarnings("deprecation")
public class MainView extends StampBaseView {
private MainViewActivityInterface mMainViewActivityInterface
...
// method to accept interface var, need to call from activity
public void initMainView(MainViewActivityInterface mainViewActivityInterface) {
mMainViewActivityInterface = mainViewActivityInterface;
}
// api success callback
public void onStampSuccess(String stampResult) {
// StampActivity.setText("onStampSuccess - " + stampResult);
mMainViewActivityInterface.stampSuccess(stampResult);
}
...
}
Now modify your StampActivity as:
public class StampActivity extends Activity implements MainViewActivityInterface {
#Override
protected void onCreate(Bundle savedInstanceState) {
...
mainView.init(metric);
mainView.initMainView(this); // this is where we are passing the current activity as interface
...
}
#Override
public void stampSuccess(String text) {
// this is where interface callback happens, start new activity here
// may do something with text here
Intent intent = new Intent(this, NewActivity.class);
startActivity(intent);
}
}
Apply the following changes to your setText() method:
public static void setText(String text) {
textView.setText(text);
if(text.startsWith("onStampSuccess"){
Intent intent = new Intent(this, nextActivity.class);
startActivity(intent);
}

Substring in Java Eclipse Project

I'm pretty new to this. I'm working on an app in eclipse to read card reader input. Currently, the card reader as usual reads out the card details all in a single row of entry (its a tract 2 reader). It will be changed to a track1 card reader, then I can use the cardHolderName text. Here's a sample card output
;1234567890111213=12345678901113141516?
I would like to;
remove the first ";" everytime a card is read
Add the first 16 digits (after the ";") to a textfield
Remove the "="
display the first 4 digits after the "=" sign in another textfield
So the two textfields should display:
Textfield1:1234567890111213
Textfield2: 12/34
I tried using the substring() method in the setText lines, but it didn't provide any results. Can anyone help identify where I'm making a mistake ?
The .java code i am working on is below; Much appreciated!
package com.square;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class Payments extends Activity {
private UpdateBytesHandler updateBytesHandler;
private UpdateBitsHandler updateBitsHandler;
private TextView decodedStringView;
private TextView strippedBinaryView;
private TextView holderName;
private TextView expiryDate;
private TextView cardNumber;
private Button startBtn;
private Button stopBtn;
private MagRead read;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
startBtn = (Button)findViewById(R.id.startbtn);
stopBtn = (Button)findViewById(R.id.stopbtn);
stopBtn.setEnabled(false);
decodedStringView = (TextView)findViewById(R.id.bytes);
strippedBinaryView = (TextView)findViewById(R.id.bits);
holderName = (TextView)findViewById(R.id.holderNameReal);
cardNumber = (TextView)findViewById(R.id.cardNumberReal);
expiryDate = (TextView)findViewById(R.id.expiry);
read = new MagRead();
read.addListener(new MagReadListener() {
#Override
public void updateBytes(String bytes) {
Message msg = new Message();
msg.obj = bytes;
updateBytesHandler.sendMessage(msg);
}
#Override
public void updateBits(String bits) {
Message msg = new Message();
msg.obj = bits;
updateBitsHandler.sendMessage(msg);
}
});
MicListener ml = new MicListener();
startBtn.setOnClickListener(ml);
stopBtn.setOnClickListener(ml);
updateBytesHandler = new UpdateBytesHandler();
updateBitsHandler = new UpdateBitsHandler();
}
#Override
protected void onDestroy() {
super.onDestroy();
read.release();
}
/**
* Listener called with the mic status button is clicked, and when the zero level or noise thresholds are changed
*/
private class MicListener implements OnClickListener{
/**
* Called when the mic button is clicked
* #param
*/
#Override
public void onClick(View v) {
if(v == stopBtn){//stop listening
stopBtn.setEnabled(false);
startBtn.setEnabled(true);
read.stop();
}else if(v == startBtn) {//start listening
stopBtn.setEnabled(true);
startBtn.setEnabled(false);
read.start();
}
}
}
private class UpdateBytesHandler extends Handler {
#Override
public void handleMessage(Message msg) {
String bytes = (String)msg.obj;
decodedStringView.setText(bytes);
}
}
private class UpdateBitsHandler extends Handler {
#Override
public void handleMessage(Message msg) {
String bits = (String)msg.obj;
strippedBinaryView.setText(bits);
}
}
private class UpdateHolderName extends Handler {
#Override
public void handleMessage(Message msg) {
String holderN = (String)msg.obj;
holderName.setText(holderN);
}
}
private class UpdateCardNumber extends Handler {
#Override
public void handleMessage(Message msg) {
String cardN = (String)msg.obj;
cardNumber.setText(cardN);
}
}
private class UpdateExpiry extends Handler {
#Override
public void handleMessage(Message msg) {
String exp = (String)msg.obj;
expiryDate.setText(exp);
}
}
}`
Consider this to your string
String data = ";1234567890111213=12345678901113141516?"
String first= data.substring(1, 17);
String second= data.substring(18, data.length()-1);
For more understanding, follow this tutorial
Check the java String method substring(i,j)
String code = ";1234567890111213=12345678901113141516?";
String first = code.substring(1,17);
String second = code.substring(18,19) + "/" + code.substring(20,21);
IMPORTANT substring() returns a new String !
Returns a new string that is a substring of this string.
So you must store the result in a variable.

Categories

Resources