[Huawei Developers] John Wo:
[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/834/235/2640091000001834235.20201001155459.36328583787410646019378812615982:50511021015744:2800:38E45EA10791E4E5A8B2E4323C9C85981EF45E81A12F108A381E32601131A31A.png"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/834/235/2640091000001834235.20201001155459.36328583787410646019378812615982:50511021015744:2800:38E45EA10791E4E5A8B2E4323C9C85981EF45E81A12F108A381E32601131A31A.png[/IMG]
​

Panorama use a specialized rotating lens camera and a curved daguerreotype plate date from the 1840s onwards.

In 1899, Kodak introduced the #4 Kodak Panorama panoramic camera for amateur photographers. These photographs were about 12” cm long and had a field of view that was 180°.

The story and the evolution of photographic artistry has been beautiful.

Huawei Panorama Kit delivers an immersive and interactive viewing experience.

By integrating Panorama Kit, apps can present users with interactive, 360-degree spherical or cylindrical panoramic images, so they can immerse in exciting 3D environments.

Features

360-degree spherical panorama, partially 360-degree spherical panorama, and cylindrical panorama

Parsing and display of panorama images in JPG, JPEG, and PNG formats

Interactive viewing of panoramic videos

Panorama view adjustment by swiping the screen or rotating the mobile phone to any degree

Interactive viewing of 360-degree spherical panoramas shot by mainstream panoramic cameras

Flexible use of panorama services, such as displaying panoramas in a certain area of your app made possible with in-app panorama display API’s.

Note: The size of a 2D image to be view is not greater than 20 MB, and the resolution is less than 16384 x 8192.

Development Overview

Prerequisite

1. Must have a Huawei Developer Account

2. Must have Android Studio 3.0 or later

3. Must have a Huawei phone with HMS 4.0.0.300 or later.

Software Requirements

1. Java SDK 1.7 or later

2. Android 5.0 or later

Preparation

1. Create an app or project in the Huawei app gallery connect.

2. Provide the SHA Key and App Package name of the project in App Information Section and enable the required API.

3. Create an Android project.

Note: Panorama SDK can be directly called by devices, without connecting to AppGallery Connect and hence it is not mandatory to download and integrate the agconnect-services.json.

Integration

1. Add below to build.gradle (project)file, under buildscript/repositories and allprojects/repositories.

Maven {url 'http://developer.huawei.com/repo/'}

2. Add below to build.gradle (app) file, under dependencies.

Implementation 'com.huawei.hms:panorama:5.0.2.301'

Adding permissions

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

Development Process

The sample application is Tourism application.

It lists all the glorious places to visit around the world and provide 360 degree view of their beauty using HMS Ring api of Panorama kit.

The application has only 1 module as of now which is to display the 7 wonders of the World.

To achieve it below classes are created.

Activity_main.xml

This class is responsible to hold the Recycler view and to list all the 7 Wonders of the world.

<?
xml version="1.0" encoding="utf-8"
?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:paddingLeft="8dp"
android:paddingRight="8dp">

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>

card_Layout.xml

This class is responsible to hold the card view design which is integrated within the Recycler view.

<?xml version="1.0" encoding="utf-8"?>

<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/card_view"
android:layout_marginLeft="-3dp"
android:layout_marginRight="0dp"
android:layout_marginBottom="5dp"
app:cardBackgroundColor="#E5E5E5"
app:cardCornerRadius="8dp"
app:cardElevation="3dp"
app:contentPadding="4dp" >

<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:id="@+id/rootLayout">

<ImageView
android:layout_width="100dp"
android:layout_height="100dp"

<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@drawable/gradient"
android:layout_margin="5dp">

<TextView
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:paddingLeft="5dp"
android:paddingRight="5dp"
android:text="7 Wonders"
android:textColor="#ff25"
android:textSize="18sp"
android:textStyle="bold" />

<TextView
android:id="@+id/location"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:drawableLeft="@drawable/ic_location_on_black_24dp"
android:gravity="center|bottom"
android:maxLines="1"
android:text="India"
android:textColor="@android:color/black"
android:textSize="14sp" />

</LinearLayout>

</LinearLayout>
</androidx.cardview.widget.CardView>
android:id="@+id/item_image"
android:layout_margin="5dp"
android:scaleType="fitXY"/>

MainActivity.java

This class is the launching activity for this module of the application and holds the implementation for Recycler View and Item click. Also responsible to launch the panorama view of the selected item.

package com.example.panoramaview; import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.huawei.hms.panorama.Panorama;
import com.huawei.hms.panorama.PanoramaInterface;
import com.huawei.hms.support.api.client.ResultCallback;

public class MainActivity extends AppCompatActivity implements TourRecyclerAdapter.OnTourClickListner {

private static final String LOG_TAG = "MainActivity";
RecyclerView recyclerView;
RecyclerView.LayoutManager layoutManager;
private TourRecyclerAdapter mTourRecyclerAdapter;
int id;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

recyclerView = findViewById(R.id.recycler_view);
layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);

//Creating object for the adapter class.
mTourRecyclerAdapter = new TourRecyclerAdapter(this);
recyclerView.setAdapter(mTourRecyclerAdapter);
}

@Override
public void onTourClick(int Position) {
id = Position;

Uri uril = SelectImageToConvert(Position);
Panorama.getInstance()
.loadImageInfo(this, uril, PanoramaInterface.IMAGE_TYPE_RING)
.setResultCallback(new MainActivity.ResultCallbackImpl());

}

//Callback method to handle the panorama view.
private class ResultCallbackImpl implements ResultCallback<PanoramaInterface.ImageInfoResult> {
@Override
public void onResult(PanoramaInterface.ImageInfoResult panoramaResult) {
if (panoramaResult == null) {
logAndToast("panoramaResult is null");
return;
}

if (panoramaResult.getStatus().isSuccess()) {
Intent intent = panoramaResult.getImageDisplayIntent();
if (intent != null) {
startActivity(intent);
} else {
logAndToast("unknown error, view intent is null");
}
} else {
logAndToast("error status : " + panoramaResult.getStatus());
}
}
}

//Method for logging.
private void logAndToast(String message) {
Log.e(LOG_TAG, message);
Toast.makeText(MainActivity.this, message, Toast.LENGTH_LONG).show();
}

//Decides the image click drawable
public Uri selectImageToConvert(int Position) {
Uri uri = null;
try{

switch (Position) {
case 0:
uri = Uri.parse("android.resource://" + getPackageName() + "/" + R.drawable.tajmahal);
break;
case 1:
uri = Uri.parse("android.resource://" + getPackageName() + "/" + R.drawable.christ_the_redeemer);
break;
case 2:
uri = Uri.parse("android.resource://" + getPackageName() + "/" + R.drawable.chichenitza);
break;
case 3:
uri = Uri.parse("android.resource://" + getPackageName() + "/" + R.drawable.greatwallchina);
break;
case 4:
uri = Uri.parse("android.resource://" + getPackageName() + "/" + R.drawable.petrajordan);
break;
case 5:
uri = Uri.parse("android.resource://" + getPackageName() + "/" + R.drawable.colosseum_rome);
break;
case 6:
uri = Uri.parse("android.resource://" + getPackageName() + "/" + R.drawable.machu_picchu);
break;
default:
throw new IllegalStateException("Unexpected value: " + Position);
}

}catch(Exception e)
{
logAndToast("Exception occurs, Please check" +e);
}

finally {
return uri;
}
}
}

TourRecyclerAdapter.java

This is an adapter class for the created recycler view. It holds the implementation for the data.

package com.example.panoramaview;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

public class TourRecyclerAdapter extends RecyclerView.Adapter<TourRecyclerAdapter.ViewHolder>{
private OnTourClickListner mOnTourClickListner;

//Constructor to handle onclickListner
public TourRecyclerAdapter(OnTourClickListner mOnTourClickListner)
{
this.mOnTourClickListner = mOnTourClickListner;
}

private String[] titles = {"Taj Mahal",
"Christ The Redeemer",
"Chichen Itza",
"Great Wall China",
"Petra",
"Colosseum",
"Machu Picchu"};

private int[] images = { R.drawable.tajmahal,
R.drawable.christ_the_redeemer,
R.drawable.chichenitza,
R.drawable.greatwallchina,
R.drawable.petrajordan,
R.drawable.colosseum_rome,
R.drawable.machu_picchu};

private String[] location = new String[]{"India-Agra",
"Rio de Janeiro-Bazil",
"Mexico",
"China-Beijing",
"Jordan",
"Rome-Italy",
"Peru"
};

@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {

View v = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.card_layout, viewGroup, false);
ViewHolder viewHolder = new ViewHolder(v,mOnTourClickListner);
return viewHolder;
}

@Override
public void onBindViewHolder(@NonNull ViewHolder viewHolder, int i) {
viewHolder.itemTitle.setText(titles[i]);
viewHolder.itemImage.setImageResource(images[i]);
viewHolder.location.setText(location[i]);
}

@Override
public int getItemCount() {
return titles.length;
}

public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

public ImageView itemImage;
public TextView itemTitle;
public TextView location;
OnTourClickListner mOnTourClickListner;

public ViewHolder(View itemView, OnTourClickListner mOnTourClickListner) {
super(itemView);
itemImage = (ImageView) itemView.findViewById(R.id.item_image);
itemTitle = (TextView) itemView.findViewById(R.id.name);
location = (TextView) itemView.findViewById(R.id.location);

this.mOnTourClickListner = mOnTourClickListner;
itemView.setOnClickListener(this);

}

@Override
public void onClick(View view) {
mOnTourClickListner.onTourClick(getAdapterPosition());
System.out.println("inside on click 1");
}
}

//OnClickListner interface
public interface OnTourClickListner{
void onTourClick(int Position);

}
}

Results

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/834/235/2640091000001834235.20201001161542.46261065669636718727636483247878:50511021015744:2800:5EC6B0E3A37B359AC1B279560570B55BF36F5787EDC4B6A86C2194D128DB783C.jpg"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/834/235/2640091000001834235.20201001161542.46261065669636718727636483247878:50511021015744:2800:5EC6B0E3A37B359AC1B279560570B55BF36F5787EDC4B6A86C2194D128DB783C.jpg[/IMG]

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/834/235/2640091000001834235.20201001165133.03911102995230509545526576892057:50511021015744:2800:5452B7889B41D3127BDD25B064B3D1E2C108BFDFF56A5A2092BD9C8BA9EEB7EB.gif"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/001/834/235/2640091000001834235.20201001165133.03911102995230509545526576892057:50511021015744:2800:5452B7889B41D3127BDD25B064B3D1E2C108BFDFF56A5A2092BD9C8BA9EEB7EB.gif[/IMG]

Conclusion

This is an awesome application to help the people seeking for in home flexibility to plan their next adventure by having realistic views for the famous places around the world.

References

https://developer.huawei.com/consumer/en/doc/development/HMSCore-Guides-V5/introduction-0000001050042264-V5