2013年11月14日

Android─spinner 下拉式選單基本用法

在Android開發app的時候,常需要做選單的選取。
但是在手機螢幕大小,無法讓我們將所有的選項都放進去螢幕中。
所以Android提供了Spinner widget,讓開發者可以在有限的畫面範圍內仍可放入所需的資料。

首先我們先在XMl檔放入兩個Spinner,一個是kind、另一個是name



     
    

    
    

    
    

     
    



在程式的功能是
在選擇kind spinner會改變 name spinner顯示的選項
在選取name 的spinner會跳出toast,show出選擇的名稱
程式碼如下
public class MainActivity extends Activity {
private ArrayAdapter listAdapter;
private ArrayAdapter nameAdapter;
private Spinner kind = null;
private Spinner name = null;
private String itemname[] = null;
//showtoast flag是用來判斷是否 name spinner有被選取
private boolean showtoast=false;

 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  initui();
  listAdapter = new ArrayAdapter(this, R.layout.spinnerlayout,
    new String[] { "肉類", "蔬菜", "水果" });
                //設定下拉式選單顯示的版面
  listAdapter.setDropDownViewResource(R.layout.spinner_dropdown);
                //設定kind spinner顯示的字串內容
  kind.setAdapter(listAdapter);
                //設定當kind spinner item選取後的動作
  kind.setOnItemSelectedListener(spinnerlistener);
 }

      //初始化UI function
      private void initui() {
  kind = (Spinner) findViewById(R.id.kind);
  name = (Spinner) findViewById(R.id.name);
 }

 AdapterView.OnItemSelectedListener spinnerlistener = new AdapterView.OnItemSelectedListener() {
  @Override
  public void onItemSelected(AdapterView adapterView, View view,
    int position, long id) {
                        //當選取的spinner是kind時
   if (adapterView.getId() == R.id.kind) {
                                 //判斷選取的種類是何種,設定相對應的字串陣列內容
    switch (adapterView.getSelectedItemPosition()) {
    case 0:
     itemname = new String[] { "牛肉", "豬肉", "雞肉" };
     break;
    case 1:
     itemname = new String[] { "白菜", "香菜", "高麗菜" };
     break;
    case 2:
     itemname = new String[] { "蘋果", "香蕉", "西瓜" };
     break;
    }
                                //當itemanme不為空時,對spinner name進行初始化
    if (itemname != null) {
     setnameitem();
    }
   } else if (adapterView.getId() == R.id.name) {
    if(showtoast!=false)
    {
    Toast.makeText(MainActivity.this,
      "您選擇" + adapterView.getSelectedItem().toString(),
      Toast.LENGTH_LONG).show();
    }
    showtoast=true;
   }
  }
  @Override
  public void onNothingSelected(AdapterView arg0) {
  }
 };

 private void setnameitem() {
  showtoast=false;
  nameAdapter = new ArrayAdapter(this, R.layout.spinnerlayout,
    itemname);
  name.setAdapter(nameAdapter);
  name.setOnItemSelectedListener(spinnerlistener);
 }
}

設定Spinner顯示字體格式 spinnerlayout.xml 程式碼如下



設定Spinner下拉式選單版面格式 spinner_dropdown.xml 程式碼如下



程式畫面如下;



參考資料
http://xapps.cc/article/280
http://jim690701.blogspot.tw/2012/11/androidspinner.html
http://stackoverflow.com/questions/4923310/android-spinner-onitemselected-setonitemselectedlistener-not-triggering




2013年10月21日

Android─Service啟動方式

當我們在使用Smartphone時,所看到的畫面都是在前端執行的程式,但還是有許多工作需要在背景執行,例如:撥放mp4下載檔案
這種需要在背景執行的功能,Android提供了一種方法─Service
讓開發者可以在Service撰寫要提供使用者在背景執行的功能。

要創立一個Service首先我們現在Manifest宣告
test_service為一個Service
程式碼如下
<service android:name=".test_service"/>

呼叫Service有兩種方式

1.Activiy透過startService去執行Service,我們將所需要在Service執行的功能寫在Service的onStartCommand裡 

2.Activity透過bindService來執行Service,我們需要在Service內加入ibinder物件,如此Activity則可透過ibinder物件使用Service裡public的method

下面的範例,我們將丟一個正整數,透過Service去幫我們做加總的動作

1.使用startService

Activity程式碼
Intent intent = new Intent(this, test_service.class);
intent.putExtra("number",10);
startService(intent);

Service程式碼
public class Uninstall_Service extends Service {
  private int getnum,total=0;
  @Override
  public void onStart(Intent intent, int startId) {
    super.onStart(intent, startId);
    Log.i("service", "enter the service");
    getnum=intent.getExtras().getInt("number");  
      for(int a=1; a<=getnum; a++)
      {
        total=total+a;    
      } 
    Log.i("service","the answer is" +total);  
  }
}

Service會在onStart裡面去做整數加總的動作

2. bind service的使用方式
小弟才疏學淺,怕解說的不詳細
此連結有對bind service使用有詳細的解說,大家可以參考


最後來簡述一下Service destory的狀況
1.使用startService,activity與service是處在獨立的狀態,所以當activity destory,service並不會跟著destory,還是會持續在背景執行;直到service自己停止,或者可由任一個activity使用stopService()。

2. 使用bind service,service與activity的ibind object是有關連的,所以當activity destory時,service也會跟著destory。 另外有一點需要注意的是,當activity進入pause 或 stop,要先unbind service,當resume時,再重新bind service。

參考連結1
參考連結2
參考連結3
參考連結4



2013年10月15日

Android─指定apk安裝位置

在Android 2.2以上的版本,支援apk可以搬移到外部的儲存空間,
例如手機儲存空間或者SD card。
Programmer也可以在撰寫app時,指定apk安裝在內部或者外部的儲存空間。 

我們只需要在manifest 加入 android:installLocation 
此宣告有三個選項

  • internalOnly:指定apk安裝在內部儲存空間
  • auto:根據系統預設值決定安裝的位置
  • preferExternal:指定apk安裝在外部的儲存空間
如果想知道系統的預設值,可以去android 的framework底下的DefaultContainerService.java
 trace source code

在android官方的文件有寫到
如果app裡面包含了以下的項目,apk是需要放在internal storage,否則無法正常運行
  • Services
  • Alarm Services
  • Input Method Engines
  • Live Wallpapers
  • Account Managers
  • Sync Adapters
  • Device Administrators
  • Broadcast Receivers listening for "boot completed"
如果想要知道更詳細的資訊,請參考下面網頁

2013年10月1日

Android ─ Service建立Dialog對話框

根據Android的文件,Service本身並沒有介面,假如我們在Service上有需要使用到對話框。
若我們使用在Activity建立對話框的方式套用在Service裡,則會產生錯誤。

會產生錯誤的原因是,在Android系統規定,正在運作的Activity UI只能被該Activity的主thread做更改。
當Service企圖更改正在執行的Activity的UI,則會導致錯誤產生。

上網搜尋找到的解決方法:將Service所顯示的對話框設定為系統的提示框。

首先必須在Manifest增加權限



程式碼如下:
public void showDialog(int title,String message){
    Log.i("service","show dialog function");
    TextView errmsg = (TextView) layout.findViewById(R.id.errmsg);
    Log.i("service", "dialog error msg:"+message);  
    errmsg.setText(Html.fromHtml(message));
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setTitle(title);
    builder.setMessage(message); 
    builder.setPositiveButton(R.string.dlg_ok, new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int whichButton) {
            dialog.dismiss();
        }
    });
    AlertDialog alert = builder.create();
    alert.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);//設定提示框為系統提示框
    alert.show();
}

參考網址

2013年9月30日

Andorid─AlertDialog操作方式

Android 的 AlertDialog 可以顯示訊息,還可以顯示列表,甚至可以是一個xml
也就是說,可以在layout編輯器裡新增一個表單(XML),裡可以放文字物件,EDITTEXT物件,按鈕物件,然後於AlertDialog 上顯示出來。


1.呼叫最基本的對話方塊(AlertDialog)

程式碼如下:
private void ShowAlertDialog()
{
 Builder MyAlertDialog = new AlertDialog.Builder(this);
 MyAlertDialog.setTitle("我是標題");  //設定dialog顯示標題
 MyAlertDialog.setMessage("顯示的內容");  //設定dialog顯示的內容
 MyAlertDialog.show();  //顯示dialog
}

2.如果要在對話方塊裡加入Button
程式碼如下:
private void ShowMsgDialog(String Msg)
{
 Builder MyAlertDialog = new AlertDialog.Builder(this);
 MyAlertDialog.setTitle("我是標題");  
 MyAlertDialog.setMessage("顯示的內容");  
 DialogInterface.OnClickListener OkClick = new DialogInterface.OnClickListener()
 {
public void onClick(DialogInterface dialog, int which) {
 //點選按鍵,所要執行的事情,如果沒有加程式碼,則會關閉dialog
}
 };
 MyAlertDialog.setNeutralButton("OK",OkClick );  //加入OK按鍵
 MyAlertDialog.show();  //顯示dialog
}

3.如果要在對話方塊裡加入多個按鈕
程式碼如下:
private void ShowMsgDialog(String Msg)
{
 Builder MyAlertDialog = new AlertDialog.Builder(this);
 MyAlertDialog.setTitle("我是標題");  
 MyAlertDialog.setMessage("顯示的內容");  
 MyAlertDialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
   @Override
   public void onClick(DialogInterface dialog, int which) {
     //按下按鈕時顯示快顯
     Toast.makeText(MainActivity.this, "您按下OK按鈕", Toast.LENGTH_SHORT).show();
     }
   });
 MyAlertDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
   @Override
   public void onClick(DialogInterface dialog, int which) {
     //按下按鈕時顯示快顯
     Toast.makeText(MainActivity.this, "您按下Cancel按鈕", Toast.LENGTH_SHORT).show();
   }
 });
 MyAlertDialog.show();  //顯示dialog
}

4.要在對話方塊的內容套入xml的layout格式
程式碼如下: 
 View layout = inflater.inflate(R.layout.uninstall_noti_scollbar, null);
 MyAlertDialog.setView(layout); //將layout置入AlertDialog內

參考連結
參考連結

2013年9月26日

Android─透過adb 修改日期

只要輸入下面的指令

adb shell date -s 2013925.130155

則系統時間會被設定為 2013年9月25號 13:01:55


參考網址

2013年9月17日

Android ─ 透過Bitmap縮小圖片

在修改Android Setting時,有時候想要修改顯示的圖片大小,但是又不想要更動原本Setting裡的layout配置。
我所採用的方式是,透過Bitamp來達到縮放icon的大小

步驟
1.先將icon圖檔讀入到bitmap
2.設定要縮放的比例
   比例算法:用新圖檔的長高/原始圖檔的長高
3.建立一個新的Martix,利用postScale設定Martix的比例
   參考網址
4.接著建立新的bitmap,透過createBitmap將原圖及Maritx等參數加入,即可建立新的被resize的      bitmap
   參考網址
5.將resize的bitmap加入到BitmapDrawable
6.最後將BitmapDrawable ,透過setImageDrawable加入到imageview去顯示

依照上去步驟,可以減少調整原先setting layout的設置,達到縮放icon的效果

程式碼如下

ImageView indicatorView = new ImageView(getContext());
   
//for resize icon
Bitmap bmp = BitmapFactory.decodeResource(getContext().getResources(), 
R.drawable.ic_tab_common_setting);
int oldwidth = bmp.getWidth();
int oldheight = bmp.getHeight();
Log.i("Alex","SettingManager====>bmp size is :"+oldwidth+","+oldheight);
float scaleWidth = 51 / (float)oldwidth;
float scaleHeight = 51 / (float)oldheight;
Log.i("Alex","SettingManager====> set scale value : "+scaleWidth + ":" + scaleHeight);
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
// create the new Bitmap object
Bitmap resizedBitmap = Bitmap.createBitmap(bmp, 0, 0, oldwidth,oldheight, matrix, true);
BitmapDrawable bmd = new BitmapDrawable(resizedBitmap);
indicatorView.setBackgroundResource(R.drawable.bg_tab_title);
indicatorView.setImageDrawable(bmd);



其他參考網頁1
其他參考網頁2

2013年9月11日

Android─偵測網路連線狀態by ConnectivityManager

Android 手機,目前是否連上網路,是用哪種方式連上網路,wifi or 行動網路,現在網路是不是在漫遊中,我們都可以透過ConnectivityManager這個class取得相關的資訊

要判斷wifi或者行動網路是否有連線
首先要先加入權限

再使用下面程式碼

ConnectivityManager manager = (ConnectivityManager) 
getSystemService(CONNECTIVITY_SERVICE);
//For Data network check
boolean is3g = 
manager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).isConnectedOrConnecting();
//For WiFi Check
boolean isWifi = 
manager.getNetworkInfo(ConnectivityManager.TYPE_WIFI).isConnectedOrConnecting();

is3g true 代表行動網路有連線  false代表沒有

isWifi true 代表wifi有連線 false代表沒有

若想要知道網路的相關狀態
我們可以使用

ConnectivityManager CM = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = CM.getActiveNetworkInfo();

而當中要注意到的地方, 是在 NetworkInfo 這段, 倘若你的手機目前不在網路的服務範圍, 也就是說沒有任何方式可以連出去網路 則 CM.getActiveNetworkInfo() 取回的 Reference 會是 Null, 忘了做此判斷的話, 手機則會立刻罷工給你看 (NullPointerException) 而比較常見需要取得的資料如下:

info.getTypeName();     // 目前以何種方式連線 [WIFI]
info.getState();        // 目前連線狀態 [CONNECTED]
info.isAvailable();     // 目前網路是否可使用 [true]
info.isConnected();     // 網路是否已連接 [true]
info.isConnectedOrConnecting(); // 網路是否已連接 或 連線中 [true]
info.isFailover();      // 網路目前是否有問題 [false]
info.isRoaming();       // 網路目前是否在漫遊中 [false]

如果要偵測網路狀態改變
我們可以用一個BroadcastReceiver去監聽action
android.net.conn.CONNECTIVITY_CHANGE

android.net.wifi.WIFI_STATE_CHANGED
如此就可以得知手機的連線狀態改變

參考網址:
http://wp.me/pCXXH-2Q
http://goo.gl/Ve9SnY
http://viralpatel.net/blogs/android-internet-connection-status-network-change/
http://developer.android.com/reference/android/net/NetworkInfo.html

2013年9月5日

Android─Dialog顯示時,不能按home與back button及dialog以外的區域

當Dialog顯示時,如果不想要使用者關閉dialog
我們可以利用下面的程式碼,來達成此目的

dialog = new AlertDialog.Builder(mContext)
    .setTitle(title)
    .setMessage(message)
    .setPositiveButton(buttonTxt, listener)
    .create();
    dialog.setCanceledOnTouchOutside(false); // disable click home button and other area
    dialog.setCancelable(false);  // disable click back button

setCanceledOnTouchOutside  

設為true為可以點選dialog以外範圍的區域,false則是不行

setCancelable

設為true為可以點選back button,false則是不行

參考網頁
http://goo.gl/IkGCpQ
http://goo.gl/pjzyuc

Android─利用BroadcastReceiver接收wifi與bluetooth狀態變化

當app需要知道wifi bluetooth狀態被切換時,
我們可以透過BroadcastReceiver來監聽 wifi 與 bluetooth 的狀態
首先我們需要在onresume的狀態下去註冊wifi 與 bluetooth 狀態改變所發出的Broadcast事件
程式碼如下

@Override
public void onResume() {
    super.onResume();
    filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); \\bluetooth狀態改變事件
    filter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION); \\wifi狀態改變事件
    registerReceiver(mReceiver, filter);
}

當我們註冊完所要監聽的Broadcast事件後,我們就可以利用BroadcastReceiver來監聽註冊的事件。
程式碼如下
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        final String action = intent.getAction();
        if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED))  //收到bluetooth狀態改變
        {
          //執行想做的程式碼
        }
        else if((action.equals(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION))  //收到wifi狀態改變
        {
          //執行想做的程式碼
        }
    }
};// end of OnReceive

Android─ToggleButton 開關簡述

XML宣告

<togglebutton android:id="@+id/tb_wifi" 
android:layout_height="wrap_content" 
android:layout_width="wrap_content" 
android:text="ToggleButton">
</togglebutton>

<togglebutton android:id="@+id/tb_bt" 
android:layout_aligntop="@+id/tv_bt" 
android:layout_height="wrap_content" 
android:layout_width="wrap_content" 
android:text="ToggleButton">


IMPORT

import android.widget.ToggleButton;
import android.widget.CompoundButton;

CODE

private ToggleButton wifi_tb = (ToggleButton) findViewById(R.id.tb_wifi);
private ToggleButton bt_tb = (ToggleButton) findViewById(R.id.tb_bt);
wifi_tb.setOnCheckedChangeListener(listener);
bt_tb.setOnCheckedChangeListener(listener);

判斷togglebutton開關狀態

CompoundButton.OnCheckedChangeListener listener = new CompoundButton.OnCheckedChangeListener() {
@Override
    public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {
        if (isChecked) //ToggleButton on
        {
     switch (buttonView.getId()) //判斷哪個ToggleButton被選取
            {
         case R.id.tb_wifi:
                    //選取後要做的事情
      break;
  case R.id.tb_bt:
                    //選取後要做的事情
      break;
     }
 }      
        else //ToggleButton on
        {
     switch (buttonView.getId()) //判斷哪個ToggleButton被選取 
            {
  case R.id.tb_wifi                   
                     //取消後要做的事情
                    break;
        case R.id.tb_bt: 
                    //取消後要做的事情
     break;  
      }
 }
    }
};


參考連結

http://goo.gl/rgs3Dh
http://goo.gl/5qrzZe

Android─開啟wifi與bluetooth及偵測wifi與bluetooth狀態

Wifi開啟及狀態偵測

首先需要在Manifest.xml 加入以下三個permission





然後在程式內加入

private WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE)
if (wifiManager.isWifiEnabled()) //判斷目前wifi狀態 開啟會回傳true
    wifiManager.setWifiEnabled(false);   //把wifi關閉
else
    wifiManager.setWifiEnabled(true); //把wifi開啟

bluetooth開啟及狀態偵測

首先需要在Manifest.xml 加入以下兩個permission

然後在程式內加入

private BluetoothAdapter mBluetoothAdapter  = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter.isEnabled())\\判斷目前bluetooth狀態 開啟會回傳true
    mBluetoothAdapter.disable();  //將bluetooth關閉
else
    mBluetoothAdapter.enable();  //將buletooth開啟

參考網頁
http://goo.gl/A6anzN 
http://goo.gl/11Qi7Y 
http://goo.gl/Slssm 
http://goo.gl/xgLsp

Android─保持不休眠狀態

在Android上,要讓你的app避免進入休眠模式
有兩種方式可以使用

第一種是在Manifest.xml文件裡加入user-permission

  • <uses-permission android:name="android.permission.WAKE_LOCK">

第二種是直接在所執行的Activity中加入程式碼

getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

上述程式碼需
加在 setContentView(R.layout.activity_network_testing);   setview的程式碼之前


2013年8月28日

Android─ Action bar Navigate Up


                                                               The Up button in the action bar.

原本的up button按了會返回上一個parent activity

back與home的差別

也可以更改為返回上一頁
範例 code如下

@Override
public boolean onOptionsItemSelected(MenuItem item) { 
        switch (item.getItemId()) {
        case android.R.id.home: //為up butoon的id 
            onBackPressed();
            return true;
        }
    return super.onOptionsItemSelected(item);
}

Java─getclass() 用途

Use Object.getClass(). It returns the runtime type of the object.

Object instance = new SomeClass();
instance.getClass().getName(); //will return the name (as String) (== "SomeClass")
instance.getClass(); //will return the SomeClass' Class object
參考連結

Android─取得系統時間 和比較時間

Calendar c = Calendar.getInstance(); 
取得系統日期:year = c.get(Calendar.YEAR);
              month = c.grt(Calendar.MONTH);
              day = c.get(Calendar.DAY_OF_MONTH);
取得系統時間:hour = c.get(Calendar.HOUR_OF_DAY); 
              minute = c.get(Calendar.MINUTE);

如何比較時間
Calendar c = Calendar.getInstance();
    c.set(Calendar.MONTH, Calendar.MARCH);
    c.set(Calendar.DAY_OF_MONTH, 3);
 long time2=   c.getTimeInMillis();
 c.set(Calendar.MONTH, Calendar.AUGUST);
 c.set(Calendar.DAY_OF_MONTH, 8);   
 long time3=   c.getTimeInMillis();
 if(time>time2){
     //Logic
     if(time>time3){
         //Logic
     }
 }

2013年8月14日

Java ─ Arraylist基本操作

宣告一個新的arraylist
 ArrayList arlist=new ArrayList(); 

 加入字串進入arraylist 
 arlist.add("First Element"); 
 arlist.add("Second Element"); 

 取得arraylist內容 
 arlist.get(0); 
 arlist.get(1);

 清空arraylist所有資料 arlist.clear();

參考來源

Android ─ 如何將string.xml資料變成字串

<string name="content">我是顯示內容</string>

透過layout 設定
<TextView<
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/content">
</TextView>

java程式碼 設定
text.setText(getString(R.string.content));

設定為字串變數

在activity下
this.getString(R.string.content);

在非activity下
context.getString(R.string.content);
application.getString(R.string.content);

Android ─ Textview 顯示html語法內容

需要
import android.text.Html;

範例程式碼:
mytextview.setText(Html.fromHtml("<h1>&hearts;zcbbupt</h1>&#8226; <b>foo</b><br/> &#8226; bar<br/> &#8226; baz<br/>"));
則mytextview則會顯示html語法的內容

目前支援的Html tag如下
  • br
  • p
  • div
  • em
  • b
  • strong
  • cite
  • dfn
  • i
  • big
  • small
  • font
  • blockquote
  • tt
  • monospace
  • a
  • u
  • sup
  • sub


由於沒有支援 li tag,所以如果想要有bullet效果
可以利用ASCII碼來顯示 bullet 黑點

程式碼如下
mytextview.setText(Html.fromHtml("&#8226;item1<br> &#8226;item2<br>"));

結果如下
  • item1
  • item2

Java ─ int string 轉換

int to string


  1. String stringValue = Integer.toString(12345);
  2. String stringValue = String.valueOf(12345);
  3. String stringValue = new String(""+12345);

String to int


  1.  int intValue = Integer.valueOf("12345");
  2.  int intValue = Integer.parseInt("12345");


Android ─ Intent 傳送int,取得int方式

傳入參數方式

public void onClick(DialogInterface dialog, int id) {
       Intent intent = new Intent(mContext, org.gpsagenda.DetailsContainer.class);
       intent.putExtra("id", item.ID());
       mContext.startActivity(intent);
   }

接收參數方式

int id = getIntent().getExtras().getInt("id");

2013年8月13日

Android install / uninstall APK by Intent

使用此方法,會有提示視窗

參考連結

Install APK using Intent
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
startActivity(intent);
Uninstall APK using Intent:
Intent intent = new Intent(Intent.ACTION_DELETE, Uri.fromParts("package",
getPackageManager().getPackageArchiveInfo(apkUri.getPath(), 0).packageName,null));
startActivity(intent);