Skip to content

Commit

Permalink
Consumer Example
Browse files Browse the repository at this point in the history
  • Loading branch information
Newtron Labs committed Mar 19, 2017
1 parent 2ca1cf9 commit 4c5336f
Show file tree
Hide file tree
Showing 26 changed files with 746 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Expand Up @@ -40,3 +40,5 @@ captures/
*.jks

SmProducer/app/proguard-rules.pro

SmConsumer/app/proguard-rules.pro
9 changes: 9 additions & 0 deletions SmConsumer/.gitignore
@@ -0,0 +1,9 @@
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
.externalNativeBuild
1 change: 1 addition & 0 deletions SmConsumer/app/.gitignore
@@ -0,0 +1 @@
/build
27 changes: 27 additions & 0 deletions SmConsumer/app/build.gradle
@@ -0,0 +1,27 @@
apply plugin: 'com.android.application'

android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
defaultConfig {
applicationId "com.newtronlabs.smconsumerdemo"
minSdkVersion 13
targetSdkVersion 25
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:25.2.0'

// Shared Memory Library
compile 'com.newtronlabs.sharedmemory:sharedmemory:1.0.3'
}
26 changes: 26 additions & 0 deletions SmConsumer/app/src/main/AndroidManifest.xml
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.newtronlabs.smconsumerdemo"
xmlns:android="http://schemas.android.com/apk/res/android">

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/NewtronLabsTheme">

<activity
android:name=".MainActivity"
android:hardwareAccelerated="false"
android:label="@string/activity_title"
android:screenOrientation="portrait"
>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>

<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>

</manifest>
@@ -0,0 +1,101 @@
package com.newtronlabs.smconsumerdemo;

import android.graphics.Bitmap;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;

import com.newtronlabs.sharedmemory.IRemoteSharedMemory;

public class MainActivity extends AppCompatActivity implements View.OnClickListener, RemoteBitmapTask.OnRemoteBitmapListener
{

/**
* Sample: Name of the Shared Memory region allocated by the producer application.
*/
private static final String mRemoteRegionName = "Test-Region";

/**
* Sample: Application id of the producer application.
*/
private static final String mRemoteAppId = "com.newtronlabs.smproducerdemo";

/**
* Shared Memory object to interact with the remote memory allocated
* by the producer application.
*/
private IRemoteSharedMemory mSharedMemory;

private ImageView mRemoteImageView;
private TextView mMessageView;
private Bitmap mLastBitmap;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

Object savedState = getLastCustomNonConfigurationInstance();
if(savedState instanceof IRemoteSharedMemory)
{
// Reuse the shared memory reference.
mSharedMemory = (IRemoteSharedMemory)savedState;
}

mRemoteImageView = (ImageView)findViewById(R.id.img_remote);
mMessageView = (TextView)findViewById(R.id.tv_message);

View content = findViewById(R.id.content_holder);
content.setOnClickListener(this);
}

@Override
public Object onRetainCustomNonConfigurationInstance()
{
// Preserve the shared memory reference across the activity config change.
return mSharedMemory;
}

@Override
public void onClick(View view)
{
if(view.getId() == R.id.content_holder)
{
/**
* Try to access the remote shared memory.
* This will fail if:
* - The remote application is not installed.
* - The remote application has not shared a region with the specified name.
*/
RemoteBitmapTask task = new RemoteBitmapTask(this, mRemoteAppId, mRemoteRegionName, this);
task.execute();
}
}

@Override
public void onBitmapRetrieved(Bitmap remoteBitmap, String producerAppId, String regionName)
{
if(remoteBitmap == null)
{
mRemoteImageView.setVisibility(View.GONE);
mMessageView.setVisibility(View.VISIBLE);
mMessageView.setText(R.string.usage_message_failed);
}
else
{
mMessageView.setVisibility(View.GONE);
mRemoteImageView.setVisibility(View.VISIBLE);
mRemoteImageView.setImageBitmap(remoteBitmap);

if(mLastBitmap != null && !mLastBitmap.isRecycled())
{
// Free the memory
mLastBitmap.recycle();
mLastBitmap = null;
}
mLastBitmap = remoteBitmap;
}
}
}
@@ -0,0 +1,107 @@
package com.newtronlabs.smconsumerdemo;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;

import com.newtronlabs.sharedmemory.IRemoteSharedMemory;
import com.newtronlabs.sharedmemory.RemoteMemoryAdapter;

import java.io.IOException;
import java.lang.ref.WeakReference;

/**
* Helper task for reading a bitmap from a Shared Memory region.
* In order for the bitmap to be loaded the Remote application must have:
* 1 - Allocated a Shared Memory region.
* 2- Written a bitmap to that region.
*/
public class RemoteBitmapTask extends AsyncTask<Void, Void, Bitmap>
{

/**
* Listener that will be notified when the Bitmap retrieval is done.
*/
public interface OnRemoteBitmapListener
{
/**
* Called when the Bitmap retrieval is done.
* @param remoteBitmap Bitmap retrieved from the remote app, null if the image could not be read.
* @param producerAppId Application ID of the remote application whose memory we tried to access.
* @param regionName Name of the region we tried to access on the remote application.
*/
void onBitmapRetrieved(Bitmap remoteBitmap, String producerAppId, String regionName);
}

//Application ID of the Android application that shared the memory.
private final String mProducerAppId;

//Name of the Shared Region as created by the remote producer app.
private final String mRegionName;

private Context mContext;

private WeakReference<OnRemoteBitmapListener> mListener;

public RemoteBitmapTask(Context context, String producerAppId, String regionName, OnRemoteBitmapListener listener)
{
mContext = context.getApplicationContext();
mProducerAppId = producerAppId;
mRegionName = regionName;
mListener = new WeakReference<OnRemoteBitmapListener>(listener);

}
@Override
protected Bitmap doInBackground(Void... voids)
{
// Try to access the memory from the remote application.
// Note: The remote application must have allocated a memory region with the same
// name or this call will fail and return null.
IRemoteSharedMemory remoteMemory = RemoteMemoryAdapter.getDefaultAdapter()
.getSharedMemory(mContext, mProducerAppId, mRegionName);

if(remoteMemory == null)
{
// Failed to access shared memory.
return null;
}

// Allocate memory to read the bitmap.
byte[] bitmapBytes = new byte[remoteMemory.getSize()];

Bitmap remoteBitmap = null;

try
{
// Read the remote memory.
remoteMemory.readBytes(bitmapBytes, 0, 0, bitmapBytes.length);
remoteBitmap = BitmapFactory.decodeByteArray(bitmapBytes, 0, bitmapBytes.length);
// Close the reference we don't need it anymore.
remoteMemory.close();
}
catch (IOException e)
{
e.printStackTrace();
}



return remoteBitmap;
}

@Override
protected void onPostExecute(Bitmap bitmap)
{
super.onPostExecute(bitmap);

OnRemoteBitmapListener listener = mListener.get();

if(listener == null)
{
return;
}

listener.onBitmapRetrieved(bitmap, mProducerAppId, mRegionName );
}
}
42 changes: 42 additions & 0 deletions SmConsumer/app/src/main/res/drawable/image_holder_background.xml
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

<item>
<shape android:shape="rectangle">
<stroke
android:width="@dimen/border_line_width"
android:color="@color/colorPrimary"/>
</shape>
</item>

<item>
<rotate
android:fromDegrees="90"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="90">
<shape android:shape="line"
>
<stroke
android:width="@dimen/border_line_width"
android:color="@color/colorPrimary"
android:dashGap="@dimen/border_dash_size"
android:dashWidth="@dimen/border_dash_size"
/>
</shape>
</rotate>
</item>

<item>
<shape android:shape="line"
>
<stroke
android:width="@dimen/border_line_width"
android:color="@color/colorPrimary"
android:dashGap="@dimen/border_dash_size"
android:dashWidth="@dimen/border_dash_size"
/>
</shape>
</item>

</layer-list>
60 changes: 60 additions & 0 deletions SmConsumer/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:id="@+id/activity_main"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.newtronlabs.smconsumerdemo.MainActivity">

<TextView
style="@style/NewtronLabsTheme.MainFont"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/app_info_header"
android:layout_marginTop="@dimen/margin_vertical_basic"
/>

<TextView
style="@style/NewtronLabsTheme.SecondaryFont"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/app_info_content"
android:layout_marginLeft="@dimen/margin_horizontal_basic"
android:layout_marginRight="@dimen/margin_horizontal_basic"
/>

<LinearLayout
android:id="@+id/content_holder"
android:layout_width="match_parent"
android:layout_height="@dimen/image_holder_min_height"
android:background="@drawable/image_holder_background"
android:layout_marginTop="@dimen/activity_vertical_margin"
android:layout_marginEnd="@dimen/activity_vertical_margin"
android:layout_marginStart="@dimen/activity_vertical_margin"
android:gravity="center">

<TextView
android:id="@+id/tv_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/NewtronLabsTheme.SecondaryFont.Important"
android:text="@string/usage_message"
android:background="?android:attr/colorBackground"
android:layout_marginEnd="@dimen/activity_vertical_margin"
android:layout_marginStart="@dimen/activity_vertical_margin"
/>

<ImageView
android:id="@+id/img_remote"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?android:attr/colorBackground"
android:visibility="gone"
/>

</LinearLayout>
</LinearLayout>
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions SmConsumer/app/src/main/res/values-w820dp/dimens.xml
@@ -0,0 +1,6 @@
<resources>
<!-- Example customization of dimensions originally defined in res/values/dimens.xml
(such as screen margins) for screens with more than 820dp of available width. This
would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
<dimen name="activity_horizontal_margin">64dp</dimen>
</resources>

0 comments on commit 4c5336f

Please sign in to comment.